|
|
|
@@ -1,8 +1,8 @@ |
|
|
|
/* |
|
|
|
* Mesa 3-D graphics library |
|
|
|
* Version: 6.5.3 |
|
|
|
* Version: 7.2 |
|
|
|
* |
|
|
|
* Copyright (C) 2007 Brian Paul All Rights Reserved. |
|
|
|
* Copyright (C) 2008 Brian Paul All Rights Reserved. |
|
|
|
* |
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a |
|
|
|
* copy of this software and associated documentation files (the "Software"), |
|
|
|
@@ -215,74 +215,110 @@ link_uniform_vars(struct gl_shader_program *shProg, |
|
|
|
* For example, if the vertex shader declared "attribute vec4 foobar" we'll |
|
|
|
* allocate a generic vertex attribute for "foobar" and plug that value into |
|
|
|
* the vertex program instructions. |
|
|
|
* But if the user called glBindAttributeLocation(), those bindings will |
|
|
|
* have priority. |
|
|
|
*/ |
|
|
|
static GLboolean |
|
|
|
_slang_resolve_attributes(struct gl_shader_program *shProg, |
|
|
|
struct gl_program *prog) |
|
|
|
const struct gl_program *origProg, |
|
|
|
struct gl_program *linkedProg) |
|
|
|
{ |
|
|
|
GLint attribMap[MAX_VERTEX_ATTRIBS]; |
|
|
|
GLuint i, j; |
|
|
|
GLbitfield usedAttributes; |
|
|
|
|
|
|
|
assert(prog->Target == GL_VERTEX_PROGRAM_ARB); |
|
|
|
assert(origProg != linkedProg); |
|
|
|
assert(origProg->Target == GL_VERTEX_PROGRAM_ARB); |
|
|
|
assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB); |
|
|
|
|
|
|
|
if (!shProg->Attributes) |
|
|
|
shProg->Attributes = _mesa_new_parameter_list(); |
|
|
|
|
|
|
|
if (linkedProg->Attributes) { |
|
|
|
_mesa_free_parameter_list(linkedProg->Attributes); |
|
|
|
} |
|
|
|
linkedProg->Attributes = _mesa_new_parameter_list(); |
|
|
|
|
|
|
|
|
|
|
|
/* Build a bitmask indicating which attribute indexes have been |
|
|
|
* explicitly bound by the user with glBindAttributeLocation(). |
|
|
|
*/ |
|
|
|
usedAttributes = 0x0; |
|
|
|
for (i = 0; i < shProg->Attributes->NumParameters; i++) { |
|
|
|
GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0]; |
|
|
|
usedAttributes |= attr; |
|
|
|
usedAttributes |= (1 << attr); |
|
|
|
} |
|
|
|
|
|
|
|
/* initialize the generic attribute map entries to -1 */ |
|
|
|
for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) { |
|
|
|
attribMap[i] = -1; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* Scan program for generic attribute references |
|
|
|
*/ |
|
|
|
for (i = 0; i < prog->NumInstructions; i++) { |
|
|
|
struct prog_instruction *inst = prog->Instructions + i; |
|
|
|
for (i = 0; i < linkedProg->NumInstructions; i++) { |
|
|
|
struct prog_instruction *inst = linkedProg->Instructions + i; |
|
|
|
for (j = 0; j < 3; j++) { |
|
|
|
if (inst->SrcReg[j].File == PROGRAM_INPUT && |
|
|
|
inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) { |
|
|
|
/* this is a generic attrib */ |
|
|
|
const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0; |
|
|
|
const char *name = prog->Attributes->Parameters[k].Name; |
|
|
|
/* See if this attrib name is in the program's attribute list |
|
|
|
* (i.e. was bound by the user). |
|
|
|
/* |
|
|
|
* OK, we've found a generic vertex attribute reference. |
|
|
|
*/ |
|
|
|
GLint index = _mesa_lookup_parameter_index(shProg->Attributes, |
|
|
|
-1, name); |
|
|
|
GLint attr; |
|
|
|
if (index >= 0) { |
|
|
|
/* found, user must have specified a binding */ |
|
|
|
attr = shProg->Attributes->Parameters[index].StateIndexes[0]; |
|
|
|
} |
|
|
|
else { |
|
|
|
/* Not found, choose our own attribute number. |
|
|
|
* Start at 1 since generic attribute 0 always aliases |
|
|
|
* glVertex/position. |
|
|
|
const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0; |
|
|
|
|
|
|
|
GLint attr = attribMap[k]; |
|
|
|
|
|
|
|
if (attr < 0) { |
|
|
|
/* Need to figure out attribute mapping now. |
|
|
|
*/ |
|
|
|
const char *name = origProg->Attributes->Parameters[k].Name; |
|
|
|
const GLint size = origProg->Attributes->Parameters[k].Size; |
|
|
|
const GLenum type =origProg->Attributes->Parameters[k].DataType; |
|
|
|
GLint index, attr; |
|
|
|
|
|
|
|
/* See if there's a user-defined attribute binding for |
|
|
|
* this name. |
|
|
|
*/ |
|
|
|
GLint size = prog->Attributes->Parameters[k].Size; |
|
|
|
GLenum datatype = prog->Attributes->Parameters[k].DataType; |
|
|
|
for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) { |
|
|
|
if (((1 << attr) & usedAttributes) == 0) |
|
|
|
break; |
|
|
|
index = _mesa_lookup_parameter_index(shProg->Attributes, |
|
|
|
-1, name); |
|
|
|
if (index >= 0) { |
|
|
|
/* Found a user-defined binding */ |
|
|
|
attr = shProg->Attributes->Parameters[index].StateIndexes[0]; |
|
|
|
} |
|
|
|
if (attr == MAX_VERTEX_ATTRIBS) { |
|
|
|
/* too many! XXX record error log */ |
|
|
|
return GL_FALSE; |
|
|
|
else { |
|
|
|
/* No user-defined binding, choose our own attribute number. |
|
|
|
* Start at 1 since generic attribute 0 always aliases |
|
|
|
* glVertex/position. |
|
|
|
*/ |
|
|
|
for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) { |
|
|
|
if (((1 << attr) & usedAttributes) == 0) |
|
|
|
break; |
|
|
|
} |
|
|
|
if (attr == MAX_VERTEX_ATTRIBS) { |
|
|
|
link_error(shProg, "Too many vertex attributes"); |
|
|
|
return GL_FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
/* mark this attribute as used */ |
|
|
|
usedAttributes |= (1 << attr); |
|
|
|
} |
|
|
|
_mesa_add_attribute(shProg->Attributes, name, size, datatype,attr); |
|
|
|
|
|
|
|
/* set the attribute as used */ |
|
|
|
usedAttributes |= 1<<attr; |
|
|
|
attribMap[k] = attr; |
|
|
|
|
|
|
|
/* Save the final name->attrib binding so it can be queried |
|
|
|
* with glGetAttributeLocation(). |
|
|
|
*/ |
|
|
|
_mesa_add_attribute(linkedProg->Attributes, name, |
|
|
|
size, type, attr); |
|
|
|
} |
|
|
|
|
|
|
|
/* update the instruction's src reg */ |
|
|
|
inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return GL_TRUE; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -344,36 +380,6 @@ _slang_update_inputs_outputs(struct gl_program *prog) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Scan a vertex program looking for instances of |
|
|
|
* (PROGRAM_INPUT, VERT_ATTRIB_GENERIC0 + oldAttrib) and replace with |
|
|
|
* (PROGRAM_INPUT, VERT_ATTRIB_GENERIC0 + newAttrib). |
|
|
|
* This is used when the user calls glBindAttribLocation on an already linked |
|
|
|
* shader program. |
|
|
|
*/ |
|
|
|
void |
|
|
|
_slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib, GLuint newAttrib) |
|
|
|
{ |
|
|
|
GLuint i, j; |
|
|
|
|
|
|
|
assert(prog->Target == GL_VERTEX_PROGRAM_ARB); |
|
|
|
|
|
|
|
for (i = 0; i < prog->NumInstructions; i++) { |
|
|
|
struct prog_instruction *inst = prog->Instructions + i; |
|
|
|
for (j = 0; j < 3; j++) { |
|
|
|
if (inst->SrcReg[j].File == PROGRAM_INPUT) { |
|
|
|
if (inst->SrcReg[j].Index == VERT_ATTRIB_GENERIC0 + oldAttrib) { |
|
|
|
inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + newAttrib; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
_slang_update_inputs_outputs(prog); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** cast wrapper */ |
|
|
|
static struct gl_vertex_program * |
|
|
|
vertex_program(struct gl_program *prog) |
|
|
|
@@ -492,9 +498,8 @@ _slang_link(GLcontext *ctx, |
|
|
|
/*_mesa_print_uniforms(shProg->Uniforms);*/ |
|
|
|
|
|
|
|
if (shProg->VertexProgram) { |
|
|
|
if (!_slang_resolve_attributes(shProg, &shProg->VertexProgram->Base)) { |
|
|
|
/*goto cleanup;*/ |
|
|
|
_mesa_problem(ctx, "_slang_resolve_attributes() failed"); |
|
|
|
if (!_slang_resolve_attributes(shProg, &vertProg->Base, |
|
|
|
&shProg->VertexProgram->Base)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
} |