📄 program.c
字号:
/**
* Add a new state reference to the parameter list.
* \param paramList - the parameter list
* \param state - an array of 6 state tokens
*
* \return index of the new parameter.
*/
GLint
_mesa_add_state_reference(struct program_parameter_list *paramList,
GLint *stateTokens)
{
/* XXX Should we parse <stateString> here and produce the parameter's
* list of STATE_* tokens here, or in the parser?
*/
GLint a, idx;
idx = add_parameter(paramList, NULL, NULL, STATE);
for (a=0; a<6; a++)
paramList->Parameters[idx].StateIndexes[a] = (enum state_index) stateTokens[a];
return idx;
}
/**
* Lookup a parameter value by name in the given parameter list.
* \return pointer to the float[4] values.
*/
GLfloat *
_mesa_lookup_parameter_value(struct program_parameter_list *paramList,
GLsizei nameLen, const char *name)
{
GLuint i;
if (!paramList)
return NULL;
if (nameLen == -1) {
/* name is null-terminated */
for (i = 0; i < paramList->NumParameters; i++) {
if (paramList->Parameters[i].Name &&
_mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
return paramList->ParameterValues[i];
}
}
else {
/* name is not null-terminated, use nameLen */
for (i = 0; i < paramList->NumParameters; i++) {
if (paramList->Parameters[i].Name &&
_mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
&& _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen)
return paramList->ParameterValues[i];
}
}
return NULL;
}
/**
* Lookup a parameter index by name in the given parameter list.
* \return index of parameter in the list.
*/
GLint
_mesa_lookup_parameter_index(struct program_parameter_list *paramList,
GLsizei nameLen, const char *name)
{
GLint i;
if (!paramList)
return -1;
if (nameLen == -1) {
/* name is null-terminated */
for (i = 0; i < (GLint) paramList->NumParameters; i++) {
if (paramList->Parameters[i].Name &&
_mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
return i;
}
}
else {
/* name is not null-terminated, use nameLen */
for (i = 0; i < (GLint) paramList->NumParameters; i++) {
if (paramList->Parameters[i].Name &&
_mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
&& _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen)
return i;
}
}
return -1;
}
/**
* 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;
}
}
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_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;
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_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;
}
}
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_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) {
/* 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 = 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 */
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_INTERNAL:
{
switch (state[1]) {
case STATE_NORMAL_SCALE:
ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
break;
default:
_mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
return;
}
}
return;
default:
_mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
return;
}
}
/**
* Loop over all the parameters in a parameter list. If the parameter
* is a GL state reference, look up the current value of that state
* variable and put it into the parameter's Value[4] array.
* This would be called at glBegin time when using a fragment program.
*/
void
_mesa_load_state_parameters(GLcontext *ctx,
struct program_parameter_list *paramList)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -