struct gl_program_parameter_list * _mesa_clone_parameter_list(const struct gl_program_parameter_list *list) { struct gl_program_parameter_list *clone; GLuint i; clone = _mesa_new_parameter_list(); if (!clone) return NULL; /** Not too efficient, but correct */ for (i = 0; i < list->NumParameters; i++) { struct gl_program_parameter *p = list->Parameters + i; GLuint size = MIN2(p->Size, 4); GLint j = _mesa_add_parameter(clone, p->Type, p->Name, size, p->DataType, list->ParameterValues[i], NULL); ASSERT(j >= 0); /* copy state indexes */ if (p->Type == PROGRAM_STATE_VAR) { GLint k; struct gl_program_parameter *q = clone->Parameters + j; for (k = 0; k < STATE_LENGTH; k++) { q->StateIndexes[k] = p->StateIndexes[k]; } } else { clone->Parameters[j].Size = p->Size; } } return clone; }
/** * Return a new parameter list which is listA + listB. */ struct gl_program_parameter_list * _mesa_combine_parameter_lists(const struct gl_program_parameter_list *listA, const struct gl_program_parameter_list *listB) { struct gl_program_parameter_list *list; if (listA) { list = _mesa_clone_parameter_list(listA); if (list && listB) { GLuint i; for (i = 0; i < listB->NumParameters; i++) { struct gl_program_parameter *param = listB->Parameters + i; _mesa_add_parameter(list, param->Type, param->Name, param->Size, param->DataType, listB->ParameterValues[i], param->StateIndexes); } } } else if (listB) { list = _mesa_clone_parameter_list(listB); } else { list = NULL; } return list; }
/** * Add a new state reference to the parameter list. * This will be used when the program contains something like this: * PARAM ambient = state.material.front.ambient; * * \param paramList the parameter list * \param stateTokens an array of 5 (STATE_LENGTH) state tokens * \return index of the new parameter. */ GLint _mesa_add_state_reference(struct gl_program_parameter_list *paramList, const gl_state_index stateTokens[STATE_LENGTH]) { const GLuint size = 4; /* XXX fix */ char *name; GLint index; /* Check if the state reference is already in the list */ for (index = 0; index < (GLint) paramList->NumParameters; index++) { if (!memcmp(paramList->Parameters[index].StateIndexes, stateTokens, STATE_LENGTH * sizeof(gl_state_index))) { return index; } } name = _mesa_program_state_string(stateTokens); index = _mesa_add_parameter(paramList, PROGRAM_STATE_VAR, name, size, GL_NONE, NULL, (gl_state_index *) stateTokens); paramList->StateFlags |= _mesa_program_state_flags(stateTokens); /* free name string here since we duplicated it in add_parameter() */ free(name); return index; }
/** * Add a sampler to the parameter list. * \param name uniform's name * \param datatype GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc. * \param index the sampler number (as seen in TEX instructions) * \return sampler index (starting at zero) or -1 if error */ GLint _mesa_add_sampler(struct gl_program_parameter_list *paramList, const char *name, GLenum datatype) { GLint i = _mesa_lookup_parameter_index(paramList, -1, name); if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) { ASSERT(paramList->Parameters[i].Size == 1); ASSERT(paramList->Parameters[i].DataType == datatype); /* already in list */ return (GLint) paramList->ParameterValues[i][0]; } else { GLuint i; const GLint size = 1; /* a sampler is basically a texture unit number */ GLfloat value[4]; GLint numSamplers = 0; for (i = 0; i < paramList->NumParameters; i++) { if (paramList->Parameters[i].Type == PROGRAM_SAMPLER) numSamplers++; } value[0] = (GLfloat) numSamplers; value[1] = value[2] = value[3] = 0.0F; (void) _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name, size, datatype, value, NULL, 0x0); return numSamplers; } }
GLint _mesa_add_sized_state_reference(struct gl_program_parameter_list *paramList, const gl_state_index16 stateTokens[STATE_LENGTH], const unsigned size, bool pad_and_align) { char *name; GLint index; /* Check if the state reference is already in the list */ for (index = 0; index < (GLint) paramList->NumParameters; index++) { if (!memcmp(paramList->Parameters[index].StateIndexes, stateTokens, sizeof(paramList->Parameters[index].StateIndexes))) { return index; } } name = _mesa_program_state_string(stateTokens); index = _mesa_add_parameter(paramList, PROGRAM_STATE_VAR, name, size, GL_NONE, NULL, stateTokens, pad_and_align); paramList->StateFlags |= _mesa_program_state_flags(stateTokens); /* free name string here since we duplicated it in add_parameter() */ free(name); return index; }
/** * Add a new named program parameter (Ex: NV_fragment_program DEFINE statement) * \return index of the new entry in the parameter list */ GLint _mesa_add_named_parameter(struct gl_program_parameter_list *paramList, const char *name, const GLfloat values[4]) { return _mesa_add_parameter(paramList, PROGRAM_NAMED_PARAM, name, 4, GL_NONE, values, NULL); }
/** * Add parameter representing a varying variable. */ GLint _mesa_add_varying(struct gl_program_parameter_list *paramList, const char *name, GLuint size) { GLint i = _mesa_lookup_parameter_index(paramList, -1, name); if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_VARYING) { /* already in list */ return i; } else { assert(size == 4); i = _mesa_add_parameter(paramList, PROGRAM_VARYING, name, size, GL_NONE, NULL, NULL); return i; } }
/** * Add a new unnamed constant to the parameter list. This will be used * when a fragment/vertex program contains something like this: * MOV r, { 0, 1, 2, 3 }; * If swizzleOut is non-null we'll search the parameter list for an * existing instance of the constant which matches with a swizzle. * * \param paramList the parameter list * \param values four float values * \param swizzleOut returns swizzle mask for accessing the constant * \return index/position of the new parameter in the parameter list. */ GLint _mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList, const gl_constant_value values[4], GLuint size, GLenum datatype, GLuint *swizzleOut) { GLint pos; ASSERT(size >= 1); ASSERT(size <= 4); if (swizzleOut && _mesa_lookup_parameter_constant(paramList, values, size, &pos, swizzleOut)) { return pos; } /* Look for empty space in an already unnamed constant parameter * to add this constant. This will only work for single-element * constants because we rely on smearing (i.e. .yyyy or .zzzz). */ if (size == 1 && swizzleOut) { for (pos = 0; pos < (GLint) paramList->NumParameters; pos++) { struct gl_program_parameter *p = paramList->Parameters + pos; if (p->Type == PROGRAM_CONSTANT && p->Size + size <= 4) { /* ok, found room */ gl_constant_value *pVal = paramList->ParameterValues[pos]; GLuint swz = p->Size; /* 1, 2 or 3 for Y, Z, W */ pVal[p->Size] = values[0]; p->Size++; *swizzleOut = MAKE_SWIZZLE4(swz, swz, swz, swz); return pos; } } } /* add a new parameter to store this constant */ pos = _mesa_add_parameter(paramList, PROGRAM_CONSTANT, NULL, size, datatype, values, NULL); if (pos >= 0 && swizzleOut) { if (size == 1) *swizzleOut = SWIZZLE_XXXX; else *swizzleOut = SWIZZLE_NOOP; } return pos; }
/** * Add a sampler to the parameter list. * \param name uniform's name * \param datatype GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc. */ GLint _mesa_add_sampler(struct gl_program_parameter_list *paramList, const char *name, GLenum datatype) { GLint i = _mesa_lookup_parameter_index(paramList, -1, name); if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) { ASSERT(paramList->Parameters[i].Size == 1); ASSERT(paramList->Parameters[i].DataType == datatype); /* already in list */ return i; } else { const GLint size = 1; /* a sampler is basically a texture unit number */ i = _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name, size, datatype, NULL, NULL); return i; } }
/** * Add a uniform to the parameter list. * Note that if the uniform is an array, size may be greater than * what's implied by the datatype. * \param name uniform's name * \param size number of floats to allocate * \param datatype GL_FLOAT_VEC3, GL_FLOAT_MAT4, etc. */ GLint _mesa_add_uniform(struct gl_program_parameter_list *paramList, const char *name, GLuint size, GLenum datatype) { GLint i = _mesa_lookup_parameter_index(paramList, -1, name); ASSERT(datatype != GL_NONE); if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_UNIFORM) { ASSERT(paramList->Parameters[i].Size == size); ASSERT(paramList->Parameters[i].DataType == datatype); /* already in list */ return i; } else { i = _mesa_add_parameter(paramList, PROGRAM_UNIFORM, name, size, datatype, NULL, NULL); return i; } }
/** * Add a new named constant to the parameter list. * This will be used when the program contains something like this: * PARAM myVals = { 0, 1, 2, 3 }; * * \param paramList the parameter list * \param name the name for the constant * \param values four float values * \return index/position of the new parameter in the parameter list */ GLint _mesa_add_named_constant(struct gl_program_parameter_list *paramList, const char *name, const GLfloat values[4], GLuint size) { #if 0 /* disable this for now -- we need to save the name! */ GLint pos; GLuint swizzle; ASSERT(size == 4); /* XXX future feature */ /* check if we already have this constant */ if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) { return pos; } #endif size = 4; /** XXX fix */ return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name, size, GL_NONE, values, NULL); }
/** * Add parameter representing a vertex program attribute. * \param size size of attribute (in floats), may be -1 if unknown * \param attrib the attribute index, or -1 if unknown */ GLint _mesa_add_attribute(struct gl_program_parameter_list *paramList, const char *name, GLint size, GLint attrib) { GLint i = _mesa_lookup_parameter_index(paramList, -1, name); if (i >= 0) { /* replace */ if (attrib < 0) attrib = i; paramList->Parameters[i].StateIndexes[0] = attrib; } else { /* add */ gl_state_index state[STATE_LENGTH]; state[0] = (gl_state_index) attrib; if (size < 0) size = 4; i = _mesa_add_parameter(paramList, PROGRAM_INPUT, name, size, GL_NONE, NULL, state); } return i; }
/** * Add a new named constant to the parameter list. * This will be used when the program contains something like this: * PARAM myVals = { 0, 1, 2, 3 }; * * \param paramList the parameter list * \param name the name for the constant * \param values four float values * \return index/position of the new parameter in the parameter list */ GLint _mesa_add_named_constant(struct gl_program_parameter_list *paramList, const char *name, const gl_constant_value values[4], GLuint size) { /* first check if this is a duplicate constant */ GLint pos; for (pos = 0; pos < (GLint)paramList->NumParameters; pos++) { const gl_constant_value *pvals = paramList->ParameterValues[pos]; if (pvals[0].u == values[0].u && pvals[1].u == values[1].u && pvals[2].u == values[2].u && pvals[3].u == values[3].u && strcmp(paramList->Parameters[pos].Name, name) == 0) { /* Same name and value is already in the param list - reuse it */ return pos; } } /* not found, add new parameter */ return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name, size, GL_NONE, values, NULL); }
/** * Add a new state reference to the parameter list. * This will be used when the program contains something like this: * PARAM ambient = state.material.front.ambient; * * \param paramList the parameter list * \param stateTokens an array of 5 (STATE_LENGTH) state tokens * \return index of the new parameter. */ GLint _mesa_add_state_reference(struct gl_program_parameter_list *paramList, const gl_state_index stateTokens[STATE_LENGTH]) { const GLuint size = 4; /* XXX fix */ const char *name; GLint index; /* Check if the state reference is already in the list */ for (index = 0; index < (GLint) paramList->NumParameters; index++) { GLuint i, match = 0; for (i = 0; i < STATE_LENGTH; i++) { if (paramList->Parameters[index].StateIndexes[i] == stateTokens[i]) { match++; } else { break; } } if (match == STATE_LENGTH) { /* this state reference is already in the parameter list */ return index; } } name = _mesa_program_state_string(stateTokens); index = _mesa_add_parameter(paramList, PROGRAM_STATE_VAR, name, size, GL_NONE, NULL, (gl_state_index *) stateTokens); paramList->StateFlags |= _mesa_program_state_flags(stateTokens); /* free name string here since we duplicated it in add_parameter() */ _mesa_free((void *) name); return index; }
/** * Called in ProgramStringNotify, we need to fill the metadata of the * gl_program attached to the ati_fragment_shader */ void st_init_atifs_prog(struct gl_context *ctx, struct gl_program *prog) { /* we know this is st_fragment_program, because of st_new_ati_fs() */ struct st_fragment_program *stfp = (struct st_fragment_program *) prog; struct ati_fragment_shader *atifs = stfp->ati_fs; unsigned pass, i, r, optype, arg; static const gl_state_index fog_params_state[STATE_LENGTH] = {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0}; static const gl_state_index fog_color[STATE_LENGTH] = {STATE_FOG_COLOR, 0, 0, 0, 0}; prog->InputsRead = 0; prog->OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR); prog->SamplersUsed = 0; prog->Parameters = _mesa_new_parameter_list(); /* fill in InputsRead, SamplersUsed, TexturesUsed */ for (pass = 0; pass < atifs->NumPasses; pass++) { for (r = 0; r < MAX_NUM_FRAGMENT_REGISTERS_ATI; r++) { struct atifs_setupinst *texinst = &atifs->SetupInst[pass][r]; GLuint pass_tex = texinst->src; if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP) { /* mark which texcoords are used */ prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + pass_tex - GL_TEXTURE0_ARB); /* by default there is 1:1 mapping between samplers and textures */ prog->SamplersUsed |= (1 << r); /* the target is unknown here, it will be fixed in the draw call */ prog->TexturesUsed[r] = TEXTURE_2D_BIT; } else if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) { prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + pass_tex - GL_TEXTURE0_ARB); } } } } for (pass = 0; pass < atifs->NumPasses; pass++) { for (i = 0; i < atifs->numArithInstr[pass]; i++) { struct atifs_instruction *inst = &atifs->Instructions[pass][i]; for (optype = 0; optype < 2; optype++) { /* color, alpha */ if (inst->Opcode[optype]) { for (arg = 0; arg < inst->ArgCount[optype]; arg++) { GLint index = inst->SrcReg[optype][arg].Index; if (index == GL_PRIMARY_COLOR_EXT) { prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_COL0); } else if (index == GL_SECONDARY_INTERPOLATOR_ATI) { /* note: ATI_fragment_shader.txt never specifies what * GL_SECONDARY_INTERPOLATOR_ATI is, swrast uses * VARYING_SLOT_COL1 for this input */ prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_COL1); } } } } } } /* we may need fog */ prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_FOGC); /* we always have the ATI_fs constants, and the fog params */ for (i = 0; i < MAX_NUM_FRAGMENT_CONSTANTS_ATI; i++) { _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM, NULL, 4, GL_FLOAT, NULL, NULL); } _mesa_add_state_reference(prog->Parameters, fog_params_state); _mesa_add_state_reference(prog->Parameters, fog_color); prog->NumInstructions = 0; prog->NumTemporaries = MAX_NUM_FRAGMENT_REGISTERS_ATI + 3; /* 3 input temps for arith ops */ prog->NumParameters = MAX_NUM_FRAGMENT_CONSTANTS_ATI + 2; /* 2 state variables for fog */ }