#include "glheader.h"
#include "imports.h"
#include "macros.h"
#include "prog_instruction.h"
#include "prog_parameter.h"
#include "prog_statevars.h"
struct gl_program_parameter_list *
_mesa_new_parameter_list(void)
{
return CALLOC_STRUCT(gl_program_parameter_list);
}
void
_mesa_free_parameter_list(struct gl_program_parameter_list *paramList)
{
GLuint i;
for (i = 0; i < paramList->NumParameters; i++) {
if (paramList->Parameters[i].Name)
_mesa_free((void *) paramList->Parameters[i].Name);
}
_mesa_free(paramList->Parameters);
if (paramList->ParameterValues)
_mesa_align_free(paramList->ParameterValues);
_mesa_free(paramList);
}
GLint
_mesa_add_parameter(struct gl_program_parameter_list *paramList,
enum register_file type, const char *name,
GLuint size, GLenum datatype, const GLfloat *values,
const gl_state_index state[STATE_LENGTH])
{
const GLuint oldNum = paramList->NumParameters;
const GLuint sz4 = (size + 3) / 4;
assert(size > 0);
if (oldNum + sz4 > paramList->Size) {
paramList->Size = paramList->Size + 4 * sz4;
paramList->Parameters = (struct gl_program_parameter *)
_mesa_realloc(paramList->Parameters,
oldNum * sizeof(struct gl_program_parameter),
paramList->Size * sizeof(struct gl_program_parameter));
paramList->ParameterValues = (GLfloat (*)[4])
_mesa_align_realloc(paramList->ParameterValues,
oldNum * 4 * sizeof(GLfloat),
paramList->Size * 4 *sizeof(GLfloat),
16);
}
if (!paramList->Parameters ||
!paramList->ParameterValues) {
paramList->NumParameters = 0;
paramList->Size = 0;
return -1;
}
else {
GLuint i;
paramList->NumParameters = oldNum + sz4;
_mesa_memset(¶mList->Parameters[oldNum], 0,
sz4 * sizeof(struct gl_program_parameter));
for (i = 0; i < sz4; i++) {
struct gl_program_parameter *p = paramList->Parameters + oldNum + i;
p->Name = name ? _mesa_strdup(name) : NULL;
p->Type = type;
p->Size = size;
p->DataType = datatype;
if (values) {
COPY_4V(paramList->ParameterValues[oldNum + i], values);
values += 4;
}
else {
ASSIGN_4V(paramList->ParameterValues[oldNum + i], 0, 0, 0, 0);
}
size -= 4;
}
if (state) {
for (i = 0; i < STATE_LENGTH; i++)
paramList->Parameters[oldNum].StateIndexes[i] = state[i];
}
return (GLint) oldNum;
}
}
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);
}
GLint
_mesa_add_named_constant(struct gl_program_parameter_list *paramList,
const char *name, const GLfloat values[4],
GLuint size)
{
#if 0
GLint pos;
GLuint swizzle;
ASSERT(size == 4);
if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) {
return pos;
}
#endif
size = 4;
return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name,
size, GL_NONE, values, NULL);
}
GLint
_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
const GLfloat values[4], GLuint size,
GLuint *swizzleOut)
{
GLint pos;
ASSERT(size >= 1);
ASSERT(size <= 4);
if (_mesa_lookup_parameter_constant(paramList, values,
size, &pos, swizzleOut)) {
return pos;
}
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) {
GLfloat *pVal = paramList->ParameterValues[pos];
GLuint swz = p->Size;
pVal[p->Size] = values[0];
p->Size++;
*swizzleOut = MAKE_SWIZZLE4(swz, swz, swz, swz);
return pos;
}
}
}
pos = _mesa_add_parameter(paramList, PROGRAM_CONSTANT, NULL,
size, GL_NONE, values, NULL);
if (pos >= 0 && swizzleOut) {
if (size == 1)
*swizzleOut = SWIZZLE_XXXX;
else
*swizzleOut = SWIZZLE_NOOP;
}
return pos;
}
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);
return i;
}
else {
i = _mesa_add_parameter(paramList, PROGRAM_UNIFORM, name,
size, datatype, NULL, NULL);
return i;
}
}
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);
return i;
}
else {
const GLint size = 1;
i = _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name,
size, datatype, NULL, NULL);
return i;
}
}
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) {
return i;
}
else {
assert(size == 4);
i = _mesa_add_parameter(paramList, PROGRAM_VARYING, name,
size, GL_NONE, NULL, NULL);
return i;
}
}
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) {
if (attrib < 0)
attrib = i;
paramList->Parameters[i].StateIndexes[0] = attrib;
}
else {
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;
}
#if 0
static GLuint
sizeof_state_reference(const GLint *stateTokens)
{
if (stateTokens[0] == STATE_MATRIX) {
GLuint rows = stateTokens[4] - stateTokens[3] + 1;
assert(rows >= 1);
assert(rows <= 4);
return rows;
}
else {
return 1;
}
}
#endif
GLint
_mesa_add_state_reference(struct gl_program_parameter_list *paramList,
const gl_state_index stateTokens[STATE_LENGTH])
{
const GLuint size = 4;
const char *name;
GLint index;
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) {
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);
_mesa_free((void *) name);
return index;
}
GLfloat *
_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList,
GLsizei nameLen, const char *name)
{
GLuint i = _mesa_lookup_parameter_index(paramList, nameLen, name);
if (i < 0)
return NULL;
else
return paramList->ParameterValues[i];
}
GLint
_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList,
GLsizei nameLen, const char *name)
{
GLint i;
if (!paramList)
return -1;
if (nameLen == -1) {
for (i = 0; i < (GLint) paramList->NumParameters; i++) {
if (paramList->Parameters[i].Name &&
_mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
return i;
}
}
else {
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;
}
GLboolean
_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list,
const GLfloat v[], GLuint vSize,
GLint *posOut, GLuint *swizzleOut)
{
GLuint i;
assert(vSize >= 1);
assert(vSize <= 4);
if (!list)
return -1;
for (i = 0; i < list->NumParameters; i++) {
if (list->Parameters[i].Type == PROGRAM_CONSTANT) {
if (!swizzleOut) {
GLuint j, match = 0;
for (j = 0; j < vSize; j++) {
if (v[j] == list->ParameterValues[i][j])
match++;
}
if (match == vSize) {
*posOut = i;
return GL_TRUE;
}
}
else {
if (vSize == 1) {
GLuint j;
for (j = 0; j < 4; j++) {
if (list->ParameterValues[i][j] == v[0]) {
*posOut = i;
*swizzleOut = MAKE_SWIZZLE4(j, j, j, j);
return GL_TRUE;
}
}
}
else if (vSize <= list->Parameters[i].Size) {
GLuint swz[4];
GLuint match = 0, j, k;
for (j = 0; j < vSize; j++) {
if (v[j] == list->ParameterValues[i][j]) {
swz[j] = j;
match++;
}
else {
for (k = 0; k < list->Parameters[i].Size; k++) {
if (v[j] == list->ParameterValues[i][k]) {
swz[j] = k;
match++;
break;
}
}
}
}
for (; j < 4; j++)
swz[j] = swz[j-1];
if (match == vSize) {
*posOut = i;
*swizzleOut = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
return GL_TRUE;
}
}
}
}
}
*posOut = -1;
return GL_FALSE;
}
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;
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);
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;
}
GLuint
_mesa_longest_parameter_name(const struct gl_program_parameter_list *list,
enum register_file type)
{
GLuint i, maxLen = 0;
if (!list)
return 0;
for (i = 0; i < list->NumParameters; i++) {
if (list->Parameters[i].Type == type) {
GLuint len = _mesa_strlen(list->Parameters[i].Name);
if (len > maxLen)
maxLen = len;
}
}
return maxLen;
}
GLuint
_mesa_num_parameters_of_type(const struct gl_program_parameter_list *list,
enum register_file type)
{
GLuint i, count = 0;
if (list) {
for (i = 0; i < list->NumParameters; i++) {
if (list->Parameters[i].Type == type)
count++;
}
}
return count;
}