static void build_f2( GLfloat *f, GLuint fstride, const GLvector4f *normal, const GLvector4f *eye ) { GLuint stride = eye->stride; GLfloat *coord = eye->start; GLuint count = eye->count; GLfloat *norm = normal->start; GLuint i; for (i=0;i<count;i++) { GLfloat u[3], two_nu; COPY_2V( u, coord ); u[2] = 0; NORMALIZE_3FV( u ); two_nu = 2.0F * DOT3(norm,u); f[0] = u[0] - norm[0] * two_nu; f[1] = u[1] - norm[1] * two_nu; f[2] = u[2] - norm[2] * two_nu; STRIDE_F(coord,stride); STRIDE_F(f,fstride); STRIDE_F(norm, normal->stride); } }
static GLfloat opengl_light_spot(GLfloat *ppli, GLfloat *v, GLfloat *sdli, GLfloat srli, GLfloat crli) { GLfloat spot_direction; GLfloat unit_ppliv[4]; GLfloat unit_sdli[4]; GLfloat cos_crli; GLfloat spot_factor; /* Get the unit vectors */ opengl_vector_unit(unit_ppliv, ppli, v); COPY_3V(unit_sdli, sdli); NORMALIZE_3FV(unit_sdli); /* Calculate the direction */ spot_direction = opengl_direction_mul(unit_ppliv, unit_sdli); cos_crli = cos(crli); if (fabs(crli - 180.0f) < 0.00000001f) return 1.0f; else { if (spot_direction >= cos_crli) { spot_factor = pow(spot_direction, srli); return spot_factor; } else { return 0.0f; } } }
static void build_m2( GLfloat f[][3], GLfloat m[], const GLvector4f *normal, const GLvector4f *eye ) { GLuint stride = eye->stride; GLfloat *coord = eye->start; GLuint count = eye->count; GLfloat *norm = normal->start; GLuint i; for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) { GLfloat u[3], two_nu, fx, fy, fz; COPY_2V( u, coord ); u[2] = 0; NORMALIZE_3FV( u ); two_nu = 2.0F * DOT3(norm,u); fx = f[i][0] = u[0] - norm[0] * two_nu; fy = f[i][1] = u[1] - norm[1] * two_nu; fz = f[i][2] = u[2] - norm[2] * two_nu; m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F); if (m[i] != 0.0F) { m[i] = 0.5F * (1.0f / sqrtf(m[i])); } } }
/* Only 3 elements are used, the 4th is ignored */ void x86_opengl_vector_unit(GLfloat *dst, GLfloat *p1, GLfloat *p2) { if (p1[3] == 0 && p2[3] !=0) ACC_SCALE_SCALAR_3V(dst, -1.0f, p1); else if (p1[3] != 0 && p2[3] ==0) COPY_3V(dst, p2); else if (p1[3] == 0 && p2[3] == 0) SUB_3V(dst, p2, p1); else SUB_3V(dst, p2, p1); NORMALIZE_3FV(dst); }
/** * Use the list of tokens in the state[] array to find global GL state * and return it in <value>. Usually, four values are returned in <value> * but matrix queries may return as many as 16 values. * This function is used for ARB vertex/fragment programs. * The program parser will produce the state[] values. */ static void _mesa_fetch_state(GLcontext *ctx, const enum state_index state[], GLfloat *value) { switch (state[0]) { case STATE_MATERIAL: { /* state[1] is either 0=front or 1=back side */ const GLuint face = (GLuint) state[1]; /* state[2] is the material attribute */ switch (state[2]) { case STATE_AMBIENT: if (face == 0) COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]); else COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT]); return; case STATE_DIFFUSE: if (face == 0) COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE]); else COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE]); return; case STATE_SPECULAR: if (face == 0) COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR]); else COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SPECULAR]); return; case STATE_EMISSION: if (face == 0) COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]); else COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION]); return; case STATE_SHININESS: if (face == 0) value[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0]; else value[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0]; value[1] = 0.0F; value[2] = 0.0F; value[3] = 1.0F; return; default: _mesa_problem(ctx, "Invalid material state in fetch_state"); return; } }; return; case STATE_LIGHT: { /* state[1] is the light number */ const GLuint ln = (GLuint) state[1]; /* state[2] is the light attribute */ switch (state[2]) { case STATE_AMBIENT: COPY_4V(value, ctx->Light.Light[ln].Ambient); return; case STATE_DIFFUSE: COPY_4V(value, ctx->Light.Light[ln].Diffuse); return; case STATE_SPECULAR: COPY_4V(value, ctx->Light.Light[ln].Specular); return; case STATE_POSITION: COPY_4V(value, ctx->Light.Light[ln].EyePosition); return; case STATE_ATTENUATION: value[0] = ctx->Light.Light[ln].ConstantAttenuation; value[1] = ctx->Light.Light[ln].LinearAttenuation; value[2] = ctx->Light.Light[ln].QuadraticAttenuation; value[3] = ctx->Light.Light[ln].SpotExponent; return; case STATE_SPOT_DIRECTION: COPY_4V(value, ctx->Light.Light[ln].EyeDirection); return; case STATE_HALF: { GLfloat eye_z[] = {0, 0, 1}; /* Compute infinite half angle vector: * half-vector = light_position + (0, 0, 1) * and then normalize. w = 0 * * light.EyePosition.w should be 0 for infinite lights. */ ADD_3V(value, eye_z, ctx->Light.Light[ln].EyePosition); NORMALIZE_3FV(value); value[3] = 0; } return; default: _mesa_problem(ctx, "Invalid light state in fetch_state"); return; } } return; case STATE_LIGHTMODEL_AMBIENT: COPY_4V(value, ctx->Light.Model.Ambient); return; case STATE_LIGHTMODEL_SCENECOLOR: if (state[1] == 0) { /* front */ GLint i; for (i = 0; i < 4; i++) { value[i] = ctx->Light.Model.Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; } } else { /* back */ GLint i; for (i = 0; i < 4; i++) { value[i] = ctx->Light.Model.Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; } } return; case STATE_LIGHTPROD: { const GLuint ln = (GLuint) state[1]; const GLuint face = (GLuint) state[2]; GLint i; ASSERT(face == 0 || face == 1); switch (state[3]) { case STATE_AMBIENT: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; return; case STATE_DIFFUSE: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Diffuse[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; return; case STATE_SPECULAR: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Specular[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; return; default: _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); return; } } return; case STATE_TEXGEN: { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; /* state[2] is the texgen attribute */ switch (state[2]) { case STATE_TEXGEN_EYE_S: COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS); return; case STATE_TEXGEN_EYE_T: COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT); return; case STATE_TEXGEN_EYE_R: COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR); return; case STATE_TEXGEN_EYE_Q: COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ); return; case STATE_TEXGEN_OBJECT_S: COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS); return; case STATE_TEXGEN_OBJECT_T: COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT); return; case STATE_TEXGEN_OBJECT_R: COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR); return; case STATE_TEXGEN_OBJECT_Q: COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ); return; default: _mesa_problem(ctx, "Invalid texgen state in fetch_state"); return; } } return; case STATE_TEXENV_COLOR: { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); } return; case STATE_FOG_COLOR: COPY_4V(value, ctx->Fog.Color); return; case STATE_FOG_PARAMS: value[0] = ctx->Fog.Density; value[1] = ctx->Fog.Start; value[2] = ctx->Fog.End; value[3] = 1.0F / (ctx->Fog.End - ctx->Fog.Start); return; case STATE_CLIPPLANE: { const GLuint plane = (GLuint) state[1]; COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); } return; case STATE_POINT_SIZE: value[0] = ctx->Point.Size; value[1] = ctx->Point.MinSize; value[2] = ctx->Point.MaxSize; value[3] = ctx->Point.Threshold; return; case STATE_POINT_ATTENUATION: value[0] = ctx->Point.Params[0]; value[1] = ctx->Point.Params[1]; value[2] = ctx->Point.Params[2]; value[3] = 1.0F; return; case STATE_MATRIX: { /* state[1] = modelview, projection, texture, etc. */ /* state[2] = which texture matrix or program matrix */ /* state[3] = first column to fetch */ /* state[4] = last column to fetch */ /* state[5] = transpose, inverse or invtrans */ const GLmatrix *matrix; const enum state_index mat = state[1]; const GLuint index = (GLuint) state[2]; const GLuint first = (GLuint) state[3]; const GLuint last = (GLuint) state[4]; const enum state_index modifier = state[5]; const GLfloat *m; GLuint row, i; if (mat == STATE_MODELVIEW) { matrix = ctx->ModelviewMatrixStack.Top; } else if (mat == STATE_PROJECTION) { matrix = ctx->ProjectionMatrixStack.Top; } else if (mat == STATE_MVP) { matrix = &ctx->_ModelProjectMatrix; } else if (mat == STATE_TEXTURE) { matrix = ctx->TextureMatrixStack[index].Top; } else if (mat == STATE_PROGRAM) { matrix = ctx->ProgramMatrixStack[index].Top; } else { _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); return; } if (modifier == STATE_MATRIX_INVERSE || modifier == STATE_MATRIX_INVTRANS) { /* XXX be sure inverse is up to date */ m = matrix->inv; } else { m = matrix->m; } if (modifier == STATE_MATRIX_TRANSPOSE || modifier == STATE_MATRIX_INVTRANS) { for (i = 0, row = first; row <= last; row++) { value[i++] = m[row * 4 + 0]; value[i++] = m[row * 4 + 1]; value[i++] = m[row * 4 + 2]; value[i++] = m[row * 4 + 3]; } } else { for (i = 0, row = first; row <= last; row++) { value[i++] = m[row + 0]; value[i++] = m[row + 4]; value[i++] = m[row + 8]; value[i++] = m[row + 12]; } } } return; case STATE_DEPTH_RANGE: value[0] = ctx->Viewport.Near; /* near */ value[1] = ctx->Viewport.Far; /* far */ value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */ value[3] = 0; return; case STATE_FRAGMENT_PROGRAM: { /* state[1] = {STATE_ENV, STATE_LOCAL} */ /* state[2] = parameter index */ int idx = state[2]; switch (state[1]) { case STATE_ENV: COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); break; case STATE_LOCAL: COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); break; default: _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); return; } } return; case STATE_VERTEX_PROGRAM: { /* state[1] = {STATE_ENV, STATE_LOCAL} */ /* state[2] = parameter index */ int idx = state[2]; switch (state[1]) { case STATE_ENV: COPY_4V(value, ctx->VertexProgram.Parameters[idx]); break; case STATE_LOCAL: COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); break; default: _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); return; } } return; default: _mesa_problem(ctx, "Invalid state in fetch_state"); return; } }
/** * Do texgen needed for glRasterPos. * \param ctx rendering context * \param vObj object-space vertex coordinate * \param vEye eye-space vertex coordinate * \param normal vertex normal * \param unit texture unit number * \param texcoord incoming texcoord and resulting texcoord */ static void compute_texgen(struct gl_context *ctx, const GLfloat vObj[4], const GLfloat vEye[4], const GLfloat normal[3], GLuint unit, GLfloat texcoord[4]) { const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; /* always compute sphere map terms, just in case */ GLfloat u[3], two_nu, rx, ry, rz, m, mInv; COPY_3V(u, vEye); NORMALIZE_3FV(u); two_nu = 2.0F * DOT3(normal, u); rx = u[0] - normal[0] * two_nu; ry = u[1] - normal[1] * two_nu; rz = u[2] - normal[2] * two_nu; m = rx * rx + ry * ry + (rz + 1.0F) * (rz + 1.0F); if (m > 0.0F) mInv = 0.5F * (1.0f / sqrtf(m)); else mInv = 0.0F; if (texUnit->TexGenEnabled & S_BIT) { switch (texUnit->GenS.Mode) { case GL_OBJECT_LINEAR: texcoord[0] = DOT4(vObj, texUnit->GenS.ObjectPlane); break; case GL_EYE_LINEAR: texcoord[0] = DOT4(vEye, texUnit->GenS.EyePlane); break; case GL_SPHERE_MAP: texcoord[0] = rx * mInv + 0.5F; break; case GL_REFLECTION_MAP: texcoord[0] = rx; break; case GL_NORMAL_MAP: texcoord[0] = normal[0]; break; default: _mesa_problem(ctx, "Bad S texgen in compute_texgen()"); return; } } if (texUnit->TexGenEnabled & T_BIT) { switch (texUnit->GenT.Mode) { case GL_OBJECT_LINEAR: texcoord[1] = DOT4(vObj, texUnit->GenT.ObjectPlane); break; case GL_EYE_LINEAR: texcoord[1] = DOT4(vEye, texUnit->GenT.EyePlane); break; case GL_SPHERE_MAP: texcoord[1] = ry * mInv + 0.5F; break; case GL_REFLECTION_MAP: texcoord[1] = ry; break; case GL_NORMAL_MAP: texcoord[1] = normal[1]; break; default: _mesa_problem(ctx, "Bad T texgen in compute_texgen()"); return; } } if (texUnit->TexGenEnabled & R_BIT) { switch (texUnit->GenR.Mode) { case GL_OBJECT_LINEAR: texcoord[2] = DOT4(vObj, texUnit->GenR.ObjectPlane); break; case GL_EYE_LINEAR: texcoord[2] = DOT4(vEye, texUnit->GenR.EyePlane); break; case GL_REFLECTION_MAP: texcoord[2] = rz; break; case GL_NORMAL_MAP: texcoord[2] = normal[2]; break; default: _mesa_problem(ctx, "Bad R texgen in compute_texgen()"); return; } } if (texUnit->TexGenEnabled & Q_BIT) { switch (texUnit->GenQ.Mode) { case GL_OBJECT_LINEAR: texcoord[3] = DOT4(vObj, texUnit->GenQ.ObjectPlane); break; case GL_EYE_LINEAR: texcoord[3] = DOT4(vEye, texUnit->GenQ.EyePlane); break; default: _mesa_problem(ctx, "Bad Q texgen in compute_texgen()"); return; } } }
/** * Compute lighting for the raster position. RGB modes computed. * \param ctx the context * \param vertex vertex location * \param normal normal vector * \param Rcolor returned color * \param Rspec returned specular color (if separate specular enabled) */ static void shade_rastpos(struct gl_context *ctx, const GLfloat vertex[4], const GLfloat normal[3], GLfloat Rcolor[4], GLfloat Rspec[4]) { /*const*/ GLfloat (*base)[3] = ctx->Light._BaseColor; GLbitfield mask; GLfloat diffuseColor[4], specularColor[4]; /* for RGB mode only */ COPY_3V(diffuseColor, base[0]); diffuseColor[3] = CLAMP( ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3], 0.0F, 1.0F ); ASSIGN_4V(specularColor, 0.0, 0.0, 0.0, 1.0); mask = ctx->Light._EnabledLights; while (mask) { const int i = u_bit_scan(&mask); struct gl_light *light = &ctx->Light.Light[i]; GLfloat attenuation = 1.0; GLfloat VP[3]; /* vector from vertex to light pos */ GLfloat n_dot_VP; GLfloat diffuseContrib[3], specularContrib[3]; if (!(light->_Flags & LIGHT_POSITIONAL)) { /* light at infinity */ COPY_3V(VP, light->_VP_inf_norm); attenuation = light->_VP_inf_spot_attenuation; } else { /* local/positional light */ GLfloat d; /* VP = vector from vertex pos to light[i].pos */ SUB_3V(VP, light->_Position, vertex); /* d = length(VP) */ d = (GLfloat) LEN_3FV( VP ); if (d > 1.0e-6F) { /* normalize VP */ GLfloat invd = 1.0F / d; SELF_SCALE_SCALAR_3V(VP, invd); } /* atti */ attenuation = 1.0F / (light->ConstantAttenuation + d * (light->LinearAttenuation + d * light->QuadraticAttenuation)); if (light->_Flags & LIGHT_SPOT) { GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection); if (PV_dot_dir<light->_CosCutoff) { continue; } else { GLfloat spot = powf(PV_dot_dir, light->SpotExponent); attenuation *= spot; } } } if (attenuation < 1e-3F) continue; n_dot_VP = DOT3( normal, VP ); if (n_dot_VP < 0.0F) { ACC_SCALE_SCALAR_3V(diffuseColor, attenuation, light->_MatAmbient[0]); continue; } /* Ambient + diffuse */ COPY_3V(diffuseContrib, light->_MatAmbient[0]); ACC_SCALE_SCALAR_3V(diffuseContrib, n_dot_VP, light->_MatDiffuse[0]); /* Specular */ { const GLfloat *h; GLfloat n_dot_h; ASSIGN_3V(specularContrib, 0.0, 0.0, 0.0); if (ctx->Light.Model.LocalViewer) { GLfloat v[3]; COPY_3V(v, vertex); NORMALIZE_3FV(v); SUB_3V(VP, VP, v); NORMALIZE_3FV(VP); h = VP; } else if (light->_Flags & LIGHT_POSITIONAL) { ACC_3V(VP, ctx->_EyeZDir); NORMALIZE_3FV(VP); h = VP; } else { h = light->_h_inf_norm; } n_dot_h = DOT3(normal, h); if (n_dot_h > 0.0F) { GLfloat shine; GLfloat spec_coef; shine = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0]; spec_coef = powf(n_dot_h, shine); if (spec_coef > 1.0e-10F) { if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) { ACC_SCALE_SCALAR_3V( specularContrib, spec_coef, light->_MatSpecular[0]); } else { ACC_SCALE_SCALAR_3V( diffuseContrib, spec_coef, light->_MatSpecular[0]); } } } } ACC_SCALE_SCALAR_3V( diffuseColor, attenuation, diffuseContrib ); ACC_SCALE_SCALAR_3V( specularColor, attenuation, specularContrib ); } Rcolor[0] = CLAMP(diffuseColor[0], 0.0F, 1.0F); Rcolor[1] = CLAMP(diffuseColor[1], 0.0F, 1.0F); Rcolor[2] = CLAMP(diffuseColor[2], 0.0F, 1.0F); Rcolor[3] = CLAMP(diffuseColor[3], 0.0F, 1.0F); Rspec[0] = CLAMP(specularColor[0], 0.0F, 1.0F); Rspec[1] = CLAMP(specularColor[1], 0.0F, 1.0F); Rspec[2] = CLAMP(specularColor[2], 0.0F, 1.0F); Rspec[3] = CLAMP(specularColor[3], 0.0F, 1.0F); }
/** * Use the list of tokens in the state[] array to find global GL state * and return it in <value>. Usually, four values are returned in <value> * but matrix queries may return as many as 16 values. * This function is used for ARB vertex/fragment programs. * The program parser will produce the state[] values. */ static void _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], GLfloat *value) { switch (state[0]) { case STATE_MATERIAL: { /* state[1] is either 0=front or 1=back side */ const GLuint face = (GLuint) state[1]; const struct gl_material *mat = &ctx->Light.Material; ASSERT(face == 0 || face == 1); /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */ ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT); /* XXX we could get rid of this switch entirely with a little * work in arbprogparse.c's parse_state_single_item(). */ /* state[2] is the material attribute */ switch (state[2]) { case STATE_AMBIENT: COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]); return; case STATE_DIFFUSE: COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]); return; case STATE_SPECULAR: COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]); return; case STATE_EMISSION: COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]); return; case STATE_SHININESS: value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0]; value[1] = 0.0F; value[2] = 0.0F; value[3] = 1.0F; return; default: _mesa_problem(ctx, "Invalid material state in fetch_state"); return; } } case STATE_LIGHT: { /* state[1] is the light number */ const GLuint ln = (GLuint) state[1]; /* state[2] is the light attribute */ switch (state[2]) { case STATE_AMBIENT: COPY_4V(value, ctx->Light.Light[ln].Ambient); return; case STATE_DIFFUSE: COPY_4V(value, ctx->Light.Light[ln].Diffuse); return; case STATE_SPECULAR: COPY_4V(value, ctx->Light.Light[ln].Specular); return; case STATE_POSITION: COPY_4V(value, ctx->Light.Light[ln].EyePosition); return; case STATE_ATTENUATION: value[0] = ctx->Light.Light[ln].ConstantAttenuation; value[1] = ctx->Light.Light[ln].LinearAttenuation; value[2] = ctx->Light.Light[ln].QuadraticAttenuation; value[3] = ctx->Light.Light[ln].SpotExponent; return; case STATE_SPOT_DIRECTION: COPY_3V(value, ctx->Light.Light[ln].SpotDirection); value[3] = ctx->Light.Light[ln]._CosCutoff; return; case STATE_SPOT_CUTOFF: value[0] = ctx->Light.Light[ln].SpotCutoff; return; case STATE_HALF_VECTOR: { static const GLfloat eye_z[] = {0, 0, 1}; GLfloat p[3]; /* Compute infinite half angle vector: * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) * light.EyePosition.w should be 0 for infinite lights. */ COPY_3V(p, ctx->Light.Light[ln].EyePosition); NORMALIZE_3FV(p); ADD_3V(value, p, eye_z); NORMALIZE_3FV(value); value[3] = 1.0; } return; default: _mesa_problem(ctx, "Invalid light state in fetch_state"); return; } } case STATE_LIGHTMODEL_AMBIENT: COPY_4V(value, ctx->Light.Model.Ambient); return; case STATE_LIGHTMODEL_SCENECOLOR: if (state[1] == 0) { /* front */ GLint i; for (i = 0; i < 3; i++) { value[i] = ctx->Light.Model.Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; } value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; } else { /* back */ GLint i; for (i = 0; i < 3; i++) { value[i] = ctx->Light.Model.Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; } value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; } return; case STATE_LIGHTPROD: { const GLuint ln = (GLuint) state[1]; const GLuint face = (GLuint) state[2]; GLint i; ASSERT(face == 0 || face == 1); switch (state[3]) { case STATE_AMBIENT: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3]; return; case STATE_DIFFUSE: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Diffuse[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; return; case STATE_SPECULAR: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Specular[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3]; return; default: _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); return; } } case STATE_TEXGEN: { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; /* state[2] is the texgen attribute */ switch (state[2]) { case STATE_TEXGEN_EYE_S: COPY_4V(value, ctx->Texture.Unit[unit].GenS.EyePlane); return; case STATE_TEXGEN_EYE_T: COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane); return; case STATE_TEXGEN_EYE_R: COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane); return; case STATE_TEXGEN_EYE_Q: COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane); return; case STATE_TEXGEN_OBJECT_S: COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane); return; case STATE_TEXGEN_OBJECT_T: COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane); return; case STATE_TEXGEN_OBJECT_R: COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane); return; case STATE_TEXGEN_OBJECT_Q: COPY_4V(value, ctx->Texture.Unit[unit].GenQ.ObjectPlane); return; default: _mesa_problem(ctx, "Invalid texgen state in fetch_state"); return; } } case STATE_TEXENV_COLOR: { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; if (_mesa_get_clamp_fragment_color(ctx)) COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); else COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped); } return; case STATE_FOG_COLOR: if (_mesa_get_clamp_fragment_color(ctx)) COPY_4V(value, ctx->Fog.Color); else COPY_4V(value, ctx->Fog.ColorUnclamped); return; case STATE_FOG_PARAMS: value[0] = ctx->Fog.Density; value[1] = ctx->Fog.Start; value[2] = ctx->Fog.End; value[3] = 1.0f / (ctx->Fog.End - ctx->Fog.Start); return; case STATE_CLIPPLANE: { const GLuint plane = (GLuint) state[1]; COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); } return; case STATE_POINT_SIZE: value[0] = ctx->Point.Size; value[1] = ctx->Point.MinSize; value[2] = ctx->Point.MaxSize; value[3] = ctx->Point.Threshold; return; case STATE_POINT_ATTENUATION: value[0] = ctx->Point.Params[0]; value[1] = ctx->Point.Params[1]; value[2] = ctx->Point.Params[2]; value[3] = 1.0F; return; case STATE_MODELVIEW_MATRIX: case STATE_PROJECTION_MATRIX: case STATE_MVP_MATRIX: case STATE_TEXTURE_MATRIX: case STATE_PROGRAM_MATRIX: { /* state[0] = modelview, projection, texture, etc. */ /* state[1] = which texture matrix or program matrix */ /* state[2] = first row to fetch */ /* state[3] = last row to fetch */ /* state[4] = transpose, inverse or invtrans */ const GLmatrix *matrix; const gl_state_index mat = state[0]; const GLuint index = (GLuint) state[1]; const GLuint firstRow = (GLuint) state[2]; const GLuint lastRow = (GLuint) state[3]; const gl_state_index modifier = state[4]; const GLfloat *m; GLuint row, i; ASSERT(firstRow >= 0); ASSERT(firstRow < 4); ASSERT(lastRow >= 0); ASSERT(lastRow < 4); if (mat == STATE_MODELVIEW_MATRIX) { matrix = ctx->ModelviewMatrixStack.Top; } else if (mat == STATE_PROJECTION_MATRIX) { matrix = ctx->ProjectionMatrixStack.Top; } else if (mat == STATE_MVP_MATRIX) { matrix = &ctx->_ModelProjectMatrix; } else if (mat == STATE_TEXTURE_MATRIX) { ASSERT(index < Elements(ctx->TextureMatrixStack)); matrix = ctx->TextureMatrixStack[index].Top; } else if (mat == STATE_PROGRAM_MATRIX) { ASSERT(index < Elements(ctx->ProgramMatrixStack)); matrix = ctx->ProgramMatrixStack[index].Top; } else { _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); return; } if (modifier == STATE_MATRIX_INVERSE || modifier == STATE_MATRIX_INVTRANS) { /* Be sure inverse is up to date: */ _math_matrix_analyse( (GLmatrix*) matrix ); m = matrix->inv; } else { m = matrix->m; } if (modifier == STATE_MATRIX_TRANSPOSE || modifier == STATE_MATRIX_INVTRANS) { for (i = 0, row = firstRow; row <= lastRow; row++) { value[i++] = m[row * 4 + 0]; value[i++] = m[row * 4 + 1]; value[i++] = m[row * 4 + 2]; value[i++] = m[row * 4 + 3]; } } else { for (i = 0, row = firstRow; row <= lastRow; row++) { value[i++] = m[row + 0]; value[i++] = m[row + 4]; value[i++] = m[row + 8]; value[i++] = m[row + 12]; } } } return; case STATE_NUM_SAMPLES: ((int *)value)[0] = ctx->DrawBuffer->Visual.samples; return; case STATE_DEPTH_RANGE: value[0] = ctx->ViewportArray[0].Near; /* near */ value[1] = ctx->ViewportArray[0].Far; /* far */ value[2] = ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near; /* far - near */ value[3] = 1.0; return; case STATE_FRAGMENT_PROGRAM: { /* state[1] = {STATE_ENV, STATE_LOCAL} */ /* state[2] = parameter index */ const int idx = (int) state[2]; switch (state[1]) { case STATE_ENV: COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); return; case STATE_LOCAL: if (!ctx->FragmentProgram.Current->Base.LocalParams) { ctx->FragmentProgram.Current->Base.LocalParams = calloc(MAX_PROGRAM_LOCAL_PARAMS, sizeof(float[4])); if (!ctx->FragmentProgram.Current->Base.LocalParams) return; } COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); return; default: _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); return; } } return; case STATE_VERTEX_PROGRAM: { /* state[1] = {STATE_ENV, STATE_LOCAL} */ /* state[2] = parameter index */ const int idx = (int) state[2]; switch (state[1]) { case STATE_ENV: COPY_4V(value, ctx->VertexProgram.Parameters[idx]); return; case STATE_LOCAL: if (!ctx->VertexProgram.Current->Base.LocalParams) { ctx->VertexProgram.Current->Base.LocalParams = calloc(MAX_PROGRAM_LOCAL_PARAMS, sizeof(float[4])); if (!ctx->VertexProgram.Current->Base.LocalParams) return; } COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); return; default: _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); return; } } return; case STATE_NORMAL_SCALE: ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); return; case STATE_INTERNAL: switch (state[1]) { case STATE_CURRENT_ATTRIB: { const GLuint idx = (GLuint) state[2]; COPY_4V(value, ctx->Current.Attrib[idx]); } return; case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: { const GLuint idx = (GLuint) state[2]; if(ctx->Light._ClampVertexColor && (idx == VERT_ATTRIB_COLOR0 || idx == VERT_ATTRIB_COLOR1)) { value[0] = CLAMP(ctx->Current.Attrib[idx][0], 0.0f, 1.0f); value[1] = CLAMP(ctx->Current.Attrib[idx][1], 0.0f, 1.0f); value[2] = CLAMP(ctx->Current.Attrib[idx][2], 0.0f, 1.0f); value[3] = CLAMP(ctx->Current.Attrib[idx][3], 0.0f, 1.0f); } else COPY_4V(value, ctx->Current.Attrib[idx]); } return; case STATE_NORMAL_SCALE: ASSIGN_4V(value, ctx->_ModelViewInvScale, ctx->_ModelViewInvScale, ctx->_ModelViewInvScale, 1); return; case STATE_TEXRECT_SCALE: /* Value = { 1/texWidth, 1/texHeight, 0, 1 }. * Used to convert unnormalized texcoords to normalized texcoords. */ { const int unit = (int) state[2]; const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; if (texObj) { struct gl_texture_image *texImage = texObj->Image[0][0]; ASSIGN_4V(value, (GLfloat) (1.0 / texImage->Width), (GLfloat) (1.0 / texImage->Height), 0.0f, 1.0f); } } return; case STATE_FOG_PARAMS_OPTIMIZED: /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) * might be more expensive than EX2 on some hw, plus it needs * another constant (e) anyway. Linear fog can now be done with a * single MAD. * linear: fogcoord * -1/(end-start) + end/(end-start) * exp: 2^-(density/ln(2) * fogcoord) * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2) */ value[0] = (ctx->Fog.End == ctx->Fog.Start) ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start)); value[1] = ctx->Fog.End * -value[0]; value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */ value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2); return; case STATE_POINT_SIZE_CLAMPED: { /* this includes implementation dependent limits, to avoid * another potentially necessary clamp. * Note: for sprites, point smooth (point AA) is ignored * and we'll clamp to MinPointSizeAA and MaxPointSize, because we * expect drivers will want to say their minimum for AA size is 0.0 * but for non-AA it's 1.0 (because normal points with size below 1.0 * need to get rounded up to 1.0, hence never disappear). GL does * not specify max clamp size for sprites, other than it needs to be * at least as large as max AA size, hence use non-AA size there. */ GLfloat minImplSize; GLfloat maxImplSize; if (ctx->Point.PointSprite) { minImplSize = ctx->Const.MinPointSizeAA; maxImplSize = ctx->Const.MaxPointSize; } else if (ctx->Point.SmoothFlag || ctx->Multisample._Enabled) { minImplSize = ctx->Const.MinPointSizeAA; maxImplSize = ctx->Const.MaxPointSizeAA; } else { minImplSize = ctx->Const.MinPointSize; maxImplSize = ctx->Const.MaxPointSize; } value[0] = ctx->Point.Size; value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize; value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize; value[3] = ctx->Point.Threshold; } return; case STATE_LIGHT_SPOT_DIR_NORMALIZED: { /* here, state[2] is the light number */ /* pre-normalize spot dir */ const GLuint ln = (GLuint) state[2]; COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection); value[3] = ctx->Light.Light[ln]._CosCutoff; } return; case STATE_LIGHT_POSITION: { const GLuint ln = (GLuint) state[2]; COPY_4V(value, ctx->Light.Light[ln]._Position); } return; case STATE_LIGHT_POSITION_NORMALIZED: { const GLuint ln = (GLuint) state[2]; COPY_4V(value, ctx->Light.Light[ln]._Position); NORMALIZE_3FV( value ); } return; case STATE_LIGHT_HALF_VECTOR: { const GLuint ln = (GLuint) state[2]; GLfloat p[3]; /* Compute infinite half angle vector: * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) * light.EyePosition.w should be 0 for infinite lights. */ COPY_3V(p, ctx->Light.Light[ln]._Position); NORMALIZE_3FV(p); ADD_3V(value, p, ctx->_EyeZDir); NORMALIZE_3FV(value); value[3] = 1.0; } return; case STATE_PT_SCALE: value[0] = ctx->Pixel.RedScale; value[1] = ctx->Pixel.GreenScale; value[2] = ctx->Pixel.BlueScale; value[3] = ctx->Pixel.AlphaScale; return; case STATE_PT_BIAS: value[0] = ctx->Pixel.RedBias; value[1] = ctx->Pixel.GreenBias; value[2] = ctx->Pixel.BlueBias; value[3] = ctx->Pixel.AlphaBias; return; case STATE_FB_SIZE: value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1); value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); value[2] = 0.0F; value[3] = 0.0F; return; case STATE_FB_WPOS_Y_TRANSFORM: /* A driver may negate this conditional by using ZW swizzle * instead of XY (based on e.g. some other state). */ if (_mesa_is_user_fbo(ctx->DrawBuffer)) { /* Identity (XY) followed by flipping Y upside down (ZW). */ value[0] = 1.0F; value[1] = 0.0F; value[2] = -1.0F; value[3] = (GLfloat) ctx->DrawBuffer->Height; } else { /* Flipping Y upside down (XY) followed by identity (ZW). */ value[0] = -1.0F; value[1] = (GLfloat) ctx->DrawBuffer->Height; value[2] = 1.0F; value[3] = 0.0F; } return; /* XXX: make sure new tokens added here are also handled in the * _mesa_program_state_flags() switch, below. */ default: /* Unknown state indexes are silently ignored here. * Drivers may do something special. */ return; } return; default: _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); return; } }
void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec, GLfloat u, GLfloat v ) { GLuint attr; for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) { struct gl_2d_map *map = exec->eval.map2[attr].map; if (map) { GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; GLfloat data[4]; ASSIGN_4V(data, 0, 0, 0, 1); _math_horner_bezier_surf(map->Points, data, uu, vv, exec->eval.map2[attr].sz, map->Uorder, map->Vorder); COPY_SZ_4V( exec->vtx.attrptr[attr], exec->vtx.attrsz[attr], data ); } } /** Vertex -- EvalCoord2f is a noop if this map not enabled: **/ if (exec->eval.map2[0].map) { struct gl_2d_map *map = exec->eval.map2[0].map; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; GLfloat vertex[4]; ASSIGN_4V(vertex, 0, 0, 0, 1); if (exec->ctx->Eval.AutoNormal) { GLfloat normal[4]; GLfloat du[4], dv[4]; _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, exec->eval.map2[0].sz, map->Uorder, map->Vorder); if (exec->eval.map2[0].sz == 4) { du[0] = du[0]*vertex[3] - du[3]*vertex[0]; du[1] = du[1]*vertex[3] - du[3]*vertex[1]; du[2] = du[2]*vertex[3] - du[3]*vertex[2]; dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0]; dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1]; dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2]; } CROSS3(normal, du, dv); NORMALIZE_3FV(normal); normal[3] = 1.0; COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL], exec->vtx.attrsz[VBO_ATTRIB_NORMAL], normal ); } else { _math_horner_bezier_surf(map->Points, vertex, uu, vv, exec->eval.map2[0].sz, map->Uorder, map->Vorder); } if (exec->vtx.attrsz[0] == 4) CALL_Vertex4fv(GET_DISPATCH(), ( vertex )); else CALL_Vertex3fv(GET_DISPATCH(), ( vertex )); } }
/** * Use the list of tokens in the state[] array to find global GL state * and return it in <value>. Usually, four values are returned in <value> * but matrix queries may return as many as 16 values. * This function is used for ARB vertex/fragment programs. * The program parser will produce the state[] values. */ static void _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], GLfloat *value) { switch (state[0]) { case STATE_MATERIAL: { /* state[1] is either 0=front or 1=back side */ const GLuint face = (GLuint) state[1]; const struct gl_material *mat = &ctx->Light.Material; ASSERT(face == 0 || face == 1); /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */ ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT); /* XXX we could get rid of this switch entirely with a little * work in arbprogparse.c's parse_state_single_item(). */ /* state[2] is the material attribute */ switch (state[2]) { case STATE_AMBIENT: COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]); return; case STATE_DIFFUSE: COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]); return; case STATE_SPECULAR: COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]); return; case STATE_EMISSION: COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]); return; case STATE_SHININESS: value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0]; value[1] = 0.0F; value[2] = 0.0F; value[3] = 1.0F; return; default: _mesa_problem(ctx, "Invalid material state in fetch_state"); return; } } case STATE_LIGHT: { /* state[1] is the light number */ const GLuint ln = (GLuint) state[1]; /* state[2] is the light attribute */ switch (state[2]) { case STATE_AMBIENT: COPY_4V(value, ctx->Light.Light[ln].Ambient); return; case STATE_DIFFUSE: COPY_4V(value, ctx->Light.Light[ln].Diffuse); return; case STATE_SPECULAR: COPY_4V(value, ctx->Light.Light[ln].Specular); return; case STATE_POSITION: COPY_4V(value, ctx->Light.Light[ln].EyePosition); return; case STATE_ATTENUATION: value[0] = ctx->Light.Light[ln].ConstantAttenuation; value[1] = ctx->Light.Light[ln].LinearAttenuation; value[2] = ctx->Light.Light[ln].QuadraticAttenuation; value[3] = ctx->Light.Light[ln].SpotExponent; return; case STATE_SPOT_DIRECTION: COPY_3V(value, ctx->Light.Light[ln].EyeDirection); value[3] = ctx->Light.Light[ln]._CosCutoff; return; case STATE_SPOT_CUTOFF: value[0] = ctx->Light.Light[ln].SpotCutoff; return; case STATE_HALF_VECTOR: { static const GLfloat eye_z[] = {0, 0, 1}; GLfloat p[3]; /* Compute infinite half angle vector: * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) * light.EyePosition.w should be 0 for infinite lights. */ COPY_3V(p, ctx->Light.Light[ln].EyePosition); NORMALIZE_3FV(p); ADD_3V(value, p, eye_z); NORMALIZE_3FV(value); value[3] = 1.0; } return; case STATE_POSITION_NORMALIZED: COPY_4V(value, ctx->Light.Light[ln].EyePosition); NORMALIZE_3FV( value ); return; default: _mesa_problem(ctx, "Invalid light state in fetch_state"); return; } } case STATE_LIGHTMODEL_AMBIENT: COPY_4V(value, ctx->Light.Model.Ambient); return; case STATE_LIGHTMODEL_SCENECOLOR: if (state[1] == 0) { /* front */ GLint i; for (i = 0; i < 3; i++) { value[i] = ctx->Light.Model.Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; } value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; } else { /* back */ GLint i; for (i = 0; i < 3; i++) { value[i] = ctx->Light.Model.Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; } value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; } return; case STATE_LIGHTPROD: { const GLuint ln = (GLuint) state[1]; const GLuint face = (GLuint) state[2]; GLint i; ASSERT(face == 0 || face == 1); switch (state[3]) { case STATE_AMBIENT: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Ambient[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3]; return; case STATE_DIFFUSE: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Diffuse[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; return; case STATE_SPECULAR: for (i = 0; i < 3; i++) { value[i] = ctx->Light.Light[ln].Specular[i] * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; } /* [3] = material alpha */ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3]; return; default: _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); return; } } case STATE_TEXGEN: { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; /* state[2] is the texgen attribute */ switch (state[2]) { case STATE_TEXGEN_EYE_S: COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS); return; case STATE_TEXGEN_EYE_T: COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT); return; case STATE_TEXGEN_EYE_R: COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR); return; case STATE_TEXGEN_EYE_Q: COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ); return; case STATE_TEXGEN_OBJECT_S: COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS); return; case STATE_TEXGEN_OBJECT_T: COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT); return; case STATE_TEXGEN_OBJECT_R: COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR); return; case STATE_TEXGEN_OBJECT_Q: COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ); return; default: _mesa_problem(ctx, "Invalid texgen state in fetch_state"); return; } } case STATE_TEXENV_COLOR: { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); } return; case STATE_FOG_COLOR: COPY_4V(value, ctx->Fog.Color); return; case STATE_FOG_PARAMS: value[0] = ctx->Fog.Density; value[1] = ctx->Fog.Start; value[2] = ctx->Fog.End; value[3] = 1.0F / (ctx->Fog.End - ctx->Fog.Start); return; case STATE_CLIPPLANE: { const GLuint plane = (GLuint) state[1]; COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); } return; case STATE_POINT_SIZE: value[0] = ctx->Point.Size; value[1] = ctx->Point.MinSize; value[2] = ctx->Point.MaxSize; value[3] = ctx->Point.Threshold; return; case STATE_POINT_ATTENUATION: value[0] = ctx->Point.Params[0]; value[1] = ctx->Point.Params[1]; value[2] = ctx->Point.Params[2]; value[3] = 1.0F; return; case STATE_MODELVIEW_MATRIX: case STATE_PROJECTION_MATRIX: case STATE_MVP_MATRIX: case STATE_TEXTURE_MATRIX: case STATE_PROGRAM_MATRIX: { /* state[0] = modelview, projection, texture, etc. */ /* state[1] = which texture matrix or program matrix */ /* state[2] = first row to fetch */ /* state[3] = last row to fetch */ /* state[4] = transpose, inverse or invtrans */ const GLmatrix *matrix; const gl_state_index mat = state[0]; const GLuint index = (GLuint) state[1]; const GLuint firstRow = (GLuint) state[2]; const GLuint lastRow = (GLuint) state[3]; const gl_state_index modifier = state[4]; const GLfloat *m; GLuint row, i; ASSERT(firstRow >= 0); ASSERT(firstRow < 4); ASSERT(lastRow >= 0); ASSERT(lastRow < 4); if (mat == STATE_MODELVIEW_MATRIX) { matrix = ctx->ModelviewMatrixStack.Top; } else if (mat == STATE_PROJECTION_MATRIX) { matrix = ctx->ProjectionMatrixStack.Top; } else if (mat == STATE_MVP_MATRIX) { matrix = &ctx->_ModelProjectMatrix; } else if (mat == STATE_TEXTURE_MATRIX) { matrix = ctx->TextureMatrixStack[index].Top; } else if (mat == STATE_PROGRAM_MATRIX) { matrix = ctx->ProgramMatrixStack[index].Top; } else { _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); return; } if (modifier == STATE_MATRIX_INVERSE || modifier == STATE_MATRIX_INVTRANS) { /* Be sure inverse is up to date: */ _math_matrix_alloc_inv( (GLmatrix *) matrix ); _math_matrix_analyse( (GLmatrix*) matrix ); m = matrix->inv; } else { m = matrix->m; } if (modifier == STATE_MATRIX_TRANSPOSE || modifier == STATE_MATRIX_INVTRANS) { for (i = 0, row = firstRow; row <= lastRow; row++) { value[i++] = m[row * 4 + 0]; value[i++] = m[row * 4 + 1]; value[i++] = m[row * 4 + 2]; value[i++] = m[row * 4 + 3]; } } else { for (i = 0, row = firstRow; row <= lastRow; row++) { value[i++] = m[row + 0]; value[i++] = m[row + 4]; value[i++] = m[row + 8]; value[i++] = m[row + 12]; } } } return; case STATE_DEPTH_RANGE: value[0] = ctx->Viewport.Near; /* near */ value[1] = ctx->Viewport.Far; /* far */ value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */ value[3] = 1.0; return; case STATE_FRAGMENT_PROGRAM: { /* state[1] = {STATE_ENV, STATE_LOCAL} */ /* state[2] = parameter index */ const int idx = (int) state[2]; switch (state[1]) { case STATE_ENV: COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); break; case STATE_LOCAL: COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); break; default: _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); return; } } return; case STATE_VERTEX_PROGRAM: { /* state[1] = {STATE_ENV, STATE_LOCAL} */ /* state[2] = parameter index */ const int idx = (int) state[2]; switch (state[1]) { case STATE_ENV: COPY_4V(value, ctx->VertexProgram.Parameters[idx]); break; case STATE_LOCAL: COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); break; default: _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); return; } } return; case STATE_NORMAL_SCALE: ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); return; case STATE_INTERNAL: switch (state[1]) { case STATE_NORMAL_SCALE: ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); return; case STATE_TEXRECT_SCALE: { const int unit = (int) state[2]; const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; if (texObj) { struct gl_texture_image *texImage = texObj->Image[0][0]; ASSIGN_4V(value, 1.0 / texImage->Width, 1.0 / texImage->Height, 0.0, 1.0); } } return; case STATE_FOG_PARAMS_OPTIMIZED: /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) * might be more expensive than EX2 on some hw, plus it needs * another constant (e) anyway. Linear fog can now be done with a * single MAD. * linear: fogcoord * -1/(end-start) + end/(end-start) * exp: 2^-(density/ln(2) * fogcoord) * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2) */ value[0] = -1.0F / (ctx->Fog.End - ctx->Fog.Start); value[1] = ctx->Fog.End / (ctx->Fog.End - ctx->Fog.Start); value[2] = ctx->Fog.Density * ONE_DIV_LN2; value[3] = ctx->Fog.Density * ONE_DIV_SQRT_LN2; return; case STATE_SPOT_DIR_NORMALIZED: { /* here, state[2] is the light number */ /* pre-normalize spot dir */ const GLuint ln = (GLuint) state[2]; COPY_3V(value, ctx->Light.Light[ln].EyeDirection); NORMALIZE_3FV(value); value[3] = ctx->Light.Light[ln]._CosCutoff; return; } default: /* unknown state indexes are silently ignored * should be handled by the driver. */ return; } return; default: _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); return; } }
static void do_EvalCoord2f( GLcontext* ctx, GLfloat u, GLfloat v ) { /** Color Index **/ if (ctx->Eval.Map2Index) { GLfloat findex; struct gl_2d_map *map = &ctx->EvalMap.Map2Index; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; _math_horner_bezier_surf(map->Points, &findex, uu, vv, 1, map->Uorder, map->Vorder); glIndexi( (GLuint) (GLint) findex ); } /** Color **/ if (ctx->Eval.Map2Color4) { GLfloat fcolor[4]; struct gl_2d_map *map = &ctx->EvalMap.Map2Color4; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; _math_horner_bezier_surf(map->Points, fcolor, uu, vv, 4, map->Uorder, map->Vorder); glColor4fv( fcolor ); } /** Normal **/ if (ctx->Eval.Map2Normal && (!ctx->Eval.AutoNormal || (!ctx->Eval.Map2Vertex3 && !ctx->Eval.Map2Vertex4))) { GLfloat normal[3]; struct gl_2d_map *map = &ctx->EvalMap.Map2Normal; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; _math_horner_bezier_surf(map->Points, normal, uu, vv, 3, map->Uorder, map->Vorder); glNormal3fv( normal ); } /** Texture Coordinates **/ if (ctx->Eval.Map2TextureCoord4) { GLfloat texcoord[4]; struct gl_2d_map *map = &ctx->EvalMap.Map2Texture4; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; _math_horner_bezier_surf(map->Points, texcoord, uu, vv, 4, map->Uorder, map->Vorder); glTexCoord4fv( texcoord ); } else if (ctx->Eval.Map2TextureCoord3) { GLfloat texcoord[4]; struct gl_2d_map *map = &ctx->EvalMap.Map2Texture3; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; _math_horner_bezier_surf(map->Points, texcoord, uu, vv, 3, map->Uorder, map->Vorder); glTexCoord3fv( texcoord ); } else if (ctx->Eval.Map2TextureCoord2) { GLfloat texcoord[4]; struct gl_2d_map *map = &ctx->EvalMap.Map2Texture2; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; _math_horner_bezier_surf(map->Points, texcoord, uu, vv, 2, map->Uorder, map->Vorder); glTexCoord2fv( texcoord ); } else if (ctx->Eval.Map2TextureCoord1) { GLfloat texcoord[4]; struct gl_2d_map *map = &ctx->EvalMap.Map2Texture1; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; _math_horner_bezier_surf(map->Points, texcoord, uu, vv, 1, map->Uorder, map->Vorder); glTexCoord1fv( texcoord ); } /** Vertex **/ if(ctx->Eval.Map2Vertex4) { GLfloat vertex[4]; GLfloat normal[3]; struct gl_2d_map *map = &ctx->EvalMap.Map2Vertex4; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; if (ctx->Eval.AutoNormal) { GLfloat du[4], dv[4]; _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, 4, map->Uorder, map->Vorder); CROSS_PROD(normal, du, dv); NORMALIZE_3FV(normal); glNormal3fv( normal ); glVertex4fv( vertex ); } else { _math_horner_bezier_surf(map->Points, vertex, uu, vv, 4, map->Uorder, map->Vorder); glVertex4fv( vertex ); } } else if (ctx->Eval.Map2Vertex3) { GLfloat vertex[4]; struct gl_2d_map *map = &ctx->EvalMap.Map2Vertex3; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; if (ctx->Eval.AutoNormal) { GLfloat du[3], dv[3]; GLfloat normal[3]; _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, 3, map->Uorder, map->Vorder); CROSS_PROD(normal, du, dv); NORMALIZE_3FV(normal); glNormal3fv( normal ); glVertex3fv( vertex ); } else { _math_horner_bezier_surf(map->Points, vertex, uu, vv, 3, map->Uorder, map->Vorder); glVertex3fv( vertex ); } } }