diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c index 525b0988903..ff5cf23beb2 100644 --- a/src/mesa/main/ffvertex_prog.c +++ b/src/mesa/main/ffvertex_prog.c @@ -1129,6 +1129,22 @@ static void build_lighting( struct tnl_program *p ) } } + /* Add more variables now that we'll use later, so that they are nicely + * sorted in the parameter list. + */ + for (i = 0; i < MAX_LIGHTS; i++) { + if (p->state->unit[i].light_enabled) { + if (p->state->unit[i].light_eyepos3_is_zero) + register_param2(p, STATE_LIGHT_POSITION_NORMALIZED, i); + else + register_param2(p, STATE_LIGHT_POSITION, i); + } + } + for (i = 0; i < MAX_LIGHTS; i++) { + if (p->state->unit[i].light_enabled) + register_param3(p, STATE_LIGHT, i, STATE_ATTENUATION); + } + for (i = 0; i < MAX_LIGHTS; i++) { if (p->state->unit[i].light_enabled) { struct ureg half = undef; diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c index ad53ed1ac8e..c30e3c252fb 100644 --- a/src/mesa/program/prog_statevars.c +++ b/src/mesa/program/prog_statevars.c @@ -129,6 +129,16 @@ fetch_state(struct gl_context *ctx, const gl_state_index16 state[], state[2] * sizeof(float)); return; } + case STATE_LIGHT_ATTENUATION_ARRAY: { + const unsigned first = state[1]; + const unsigned num_lights = state[2]; + for (unsigned i = 0; i < num_lights; i++) { + COPY_4V(value, + &ctx->Light.LightSource[first + i].ConstantAttenuation); + value += 4; + } + return; + } case STATE_LIGHTMODEL_AMBIENT: COPY_4V(value, ctx->Light.Model.Ambient); return; @@ -643,6 +653,16 @@ fetch_state(struct gl_context *ctx, const gl_state_index16 state[], } return; + case STATE_LIGHT_POSITION_ARRAY: { + const unsigned first = state[1]; + const unsigned num_lights = state[2]; + for (unsigned i = 0; i < num_lights; i++) { + COPY_4V(value, ctx->Light.Light[first + i]._Position); + value += 4; + } + return; + } + case STATE_LIGHT_POSITION_NORMALIZED: { const GLuint ln = (GLuint) state[1]; @@ -653,6 +673,19 @@ fetch_state(struct gl_context *ctx, const gl_state_index16 state[], } return; + case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: { + const unsigned first = state[1]; + const unsigned num_lights = state[2]; + for (unsigned i = 0; i < num_lights; i++) { + float p[4]; + COPY_4V(p, ctx->Light.Light[first + i]._Position); + NORMALIZE_3FV(p); + COPY_4V(value, p); + value += 4; + } + return; + } + case STATE_LIGHT_HALF_VECTOR: { const GLuint ln = (GLuint) state[1]; @@ -785,10 +818,13 @@ _mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH]) case STATE_LIGHT: case STATE_LIGHT_ARRAY: + case STATE_LIGHT_ATTENUATION_ARRAY: case STATE_LIGHTMODEL_AMBIENT: case STATE_LIGHT_SPOT_DIR_NORMALIZED: case STATE_LIGHT_POSITION: + case STATE_LIGHT_POSITION_ARRAY: case STATE_LIGHT_POSITION_NORMALIZED: + case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: case STATE_LIGHT_HALF_VECTOR: return _NEW_LIGHT_CONSTANTS; @@ -919,6 +955,9 @@ append_token(char *dst, gl_state_index k) case STATE_LIGHT_ARRAY: append(dst, "light.array"); break; + case STATE_LIGHT_ATTENUATION_ARRAY: + append(dst, "light.attenuation"); + break; case STATE_LIGHTMODEL_AMBIENT: append(dst, "lightmodel.ambient"); break; @@ -1116,11 +1155,17 @@ append_token(char *dst, gl_state_index k) append(dst, "lightSpotDirNormalized"); break; case STATE_LIGHT_POSITION: - append(dst, "lightPosition"); + append(dst, "light.position"); + break; + case STATE_LIGHT_POSITION_ARRAY: + append(dst, "light.position.array"); break; case STATE_LIGHT_POSITION_NORMALIZED: append(dst, "light.position.normalized"); break; + case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: + append(dst, "light.position.normalized.array"); + break; case STATE_LIGHT_HALF_VECTOR: append(dst, "lightHalfVector"); break; @@ -1248,6 +1293,7 @@ _mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH]) } break; case STATE_LIGHT_ARRAY: + case STATE_LIGHT_ATTENUATION_ARRAY: case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: case STATE_VERTEX_PROGRAM_ENV_ARRAY: @@ -1255,6 +1301,8 @@ _mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH]) case STATE_LIGHTPROD_ARRAY_FRONT: case STATE_LIGHTPROD_ARRAY_BACK: case STATE_LIGHTPROD_ARRAY_TWOSIDE: + case STATE_LIGHT_POSITION_ARRAY: + case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: sprintf(tmp, "[%d..%d]", state[1], state[1] + state[2] - 1); append(str, tmp); break; @@ -1460,6 +1508,40 @@ _mesa_optimize_state_parameters(struct gl_constants *consts, list->Parameters[first_param].ValueOffset; param_diff = last_param - first_param; + break; /* all done */ + } + + /* We were not able to convert light attributes to STATE_LIGHT_ARRAY. + * Another occuring pattern is light attentuation vectors placed back + * to back. Find them. + */ + if (list->Parameters[first_param].StateIndexes[2] == STATE_ATTENUATION) { + for (int i = first_param + 1; i < (int)list->NumParameters; i++) { + if (list->Parameters[i].StateIndexes[0] == STATE_LIGHT && + /* Consecutive light: */ + list->Parameters[i].StateIndexes[1] == + list->Parameters[i - 1].StateIndexes[1] + 1 && + /* Same attribute: */ + list->Parameters[i].StateIndexes[2] == + list->Parameters[i - 1].StateIndexes[2]) { + last_param = i; + continue; + } + break; /* The adjacent state var is incompatible. */ + } + if (last_param > first_param) { + param_diff = last_param - first_param; + + /* Convert the state var to STATE_LIGHT_ATTENUATION_ARRAY. */ + list->Parameters[first_param].StateIndexes[0] = + STATE_LIGHT_ATTENUATION_ARRAY; + /* Keep the light index the same. */ + /* Set the number of lights. */ + unsigned size = param_diff + 1; + list->Parameters[first_param].StateIndexes[2] = size; + list->Parameters[first_param].Size = size * 4; + break; /* all done */ + } } break; @@ -1571,6 +1653,38 @@ _mesa_optimize_state_parameters(struct gl_constants *consts, } break; } + + case STATE_LIGHT_POSITION: + case STATE_LIGHT_POSITION_NORMALIZED: + if (list->Parameters[first_param].Size != 4) + break; + + for (int i = first_param + 1; i < (int)list->NumParameters; i++) { + if (list->Parameters[i].StateIndexes[0] == + list->Parameters[i - 1].StateIndexes[0] && + /* Consecutive light: */ + list->Parameters[i].StateIndexes[1] == + list->Parameters[i - 1].StateIndexes[1] + 1) { + last_param = i; + continue; + } + break; /* The adjacent state var is incompatible. */ + } + if (last_param > first_param) { + param_diff = last_param - first_param; + + /* Convert the state var to STATE_LIGHT_POSITION_*ARRAY. */ + STATIC_ASSERT(STATE_LIGHT_POSITION + 1 == + STATE_LIGHT_POSITION_ARRAY); + STATIC_ASSERT(STATE_LIGHT_POSITION_NORMALIZED + 1 == + STATE_LIGHT_POSITION_NORMALIZED_ARRAY); + list->Parameters[first_param].StateIndexes[0]++; + /* Keep the light index the same. */ + unsigned size = param_diff + 1; + /* Set the number of lights. */ + list->Parameters[first_param].StateIndexes[2] = size; + list->Parameters[first_param].Size = size * 4; + } } if (param_diff) { diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h index 281696bba61..4b1c439dff0 100644 --- a/src/mesa/program/prog_statevars.h +++ b/src/mesa/program/prog_statevars.h @@ -57,6 +57,7 @@ typedef enum gl_state_index_ { STATE_LIGHT, /* One gl_light attribute. */ STATE_LIGHT_ARRAY, /* Multiple gl_light attributes loaded at once. */ + STATE_LIGHT_ATTENUATION_ARRAY, STATE_LIGHTMODEL_AMBIENT, STATE_LIGHTMODEL_SCENECOLOR, STATE_LIGHTPROD, @@ -121,7 +122,9 @@ typedef enum gl_state_index_ { STATE_POINT_SIZE_CLAMPED, /* includes implementation dependent size clamp */ STATE_LIGHT_SPOT_DIR_NORMALIZED, /* pre-normalized spot dir */ STATE_LIGHT_POSITION, /* object vs eye space */ + STATE_LIGHT_POSITION_ARRAY, STATE_LIGHT_POSITION_NORMALIZED, /* object vs eye space */ + STATE_LIGHT_POSITION_NORMALIZED_ARRAY, STATE_LIGHT_HALF_VECTOR, /* object vs eye space */ STATE_PT_SCALE, /**< Pixel transfer RGBA scale */ STATE_PT_BIAS, /**< Pixel transfer RGBA bias */