New functions for cloning programs and parameter lists.
diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c
index 1cf3547..6245870 100644
--- a/src/mesa/shader/program.c
+++ b/src/mesa/shader/program.c
@@ -365,6 +365,7 @@
}
+
/**
* Add a new parameter to a parameter list.
* \param paramList the list to add the parameter to
@@ -374,10 +375,10 @@
* \param type type of parameter, such as
* \return index of new parameter in the list, or -1 if error (out of mem)
*/
-static GLint
-add_parameter(struct gl_program_parameter_list *paramList,
- const char *name, const GLfloat values[4], GLuint size,
- enum register_file type)
+GLint
+_mesa_add_parameter(struct gl_program_parameter_list *paramList,
+ const char *name, const GLfloat values[4], GLuint size,
+ enum register_file type)
{
const GLuint n = paramList->NumParameters;
@@ -416,6 +417,7 @@
paramList->Parameters[n].Name = name ? _mesa_strdup(name) : NULL;
paramList->Parameters[n].Type = type;
+ paramList->Parameters[n].Size = size;
if (values)
COPY_4V(paramList->ParameterValues[n], values);
return (GLint) n;
@@ -431,7 +433,7 @@
_mesa_add_named_parameter(struct gl_program_parameter_list *paramList,
const char *name, const GLfloat values[4])
{
- return add_parameter(paramList, name, values, 4, PROGRAM_NAMED_PARAM);
+ return _mesa_add_parameter(paramList, name, values, 4, PROGRAM_NAMED_PARAM);
}
@@ -460,7 +462,7 @@
}
#endif
size = 4; /** XXX fix */
- return add_parameter(paramList, name, values, size, PROGRAM_CONSTANT);
+ return _mesa_add_parameter(paramList, name, values, size, PROGRAM_CONSTANT);
}
@@ -489,7 +491,7 @@
size, &pos, &swizzle)) {
return pos;
}
- return add_parameter(paramList, NULL, values, size, PROGRAM_CONSTANT);
+ return _mesa_add_parameter(paramList, NULL, values, size, PROGRAM_CONSTANT);
}
@@ -504,7 +506,7 @@
}
else {
assert(size == 4);
- i = add_parameter(paramList, name, NULL, size, PROGRAM_UNIFORM);
+ i = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_UNIFORM);
return i;
}
}
@@ -521,7 +523,7 @@
}
else {
assert(size == 4);
- i = add_parameter(paramList, name, NULL, size, PROGRAM_VARYING);
+ i = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_VARYING);
return i;
}
}
@@ -587,7 +589,7 @@
}
name = make_state_string(stateTokens);
- index = add_parameter(paramList, name, NULL, size, PROGRAM_STATE_VAR);
+ index = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_STATE_VAR);
if (index >= 0) {
GLuint i;
for (i = 0; i < 6; i++) {
@@ -716,6 +718,36 @@
}
+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;
+ GLint j = _mesa_add_parameter(clone, p->Name, list->ParameterValues[i],
+ p->Size, p->Type);
+ 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 < 6; k++) {
+ q->StateIndexes[k] = p->StateIndexes[k];
+ }
+ }
+ }
+
+ return clone;
+}
+
+
/**
* 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>
@@ -1526,6 +1558,82 @@
/**
+ * Return a copy of a program.
+ * XXX Problem here if the program object is actually OO-derivation
+ * made by a device driver.
+ */
+struct gl_program *
+_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog)
+{
+ struct gl_program *clone;
+
+ clone = _mesa_new_program(ctx, prog->Target, prog->Id);
+ if (!clone)
+ return NULL;
+
+ assert(clone->Target == prog->Target);
+ clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
+ clone->RefCount = 1;
+ clone->Format = prog->Format;
+ clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
+ if (!clone->Instructions) {
+ _mesa_delete_program(ctx, clone);
+ return NULL;
+ }
+ memcpy(clone->Instructions, prog->Instructions,
+ prog->NumInstructions * sizeof(struct prog_instruction));
+ clone->InputsRead = prog->InputsRead;
+ clone->OutputsWritten = prog->OutputsWritten;
+ clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
+ memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
+ clone->Varying = _mesa_clone_parameter_list(prog->Varying);
+ memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
+ clone->NumInstructions = prog->NumInstructions;
+ clone->NumTemporaries = prog->NumTemporaries;
+ clone->NumParameters = prog->NumParameters;
+ clone->NumAttributes = prog->NumAttributes;
+ clone->NumAddressRegs = prog->NumAddressRegs;
+ clone->NumNativeInstructions = prog->NumNativeInstructions;
+ clone->NumNativeTemporaries = prog->NumNativeTemporaries;
+ clone->NumNativeParameters = prog->NumNativeParameters;
+ clone->NumNativeAttributes = prog->NumNativeAttributes;
+ clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
+
+ switch (prog->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ {
+ const struct gl_vertex_program *vp
+ = (const struct gl_vertex_program *) prog;
+ struct gl_vertex_program *vpc = (struct gl_vertex_program *) clone;
+ vpc->IsPositionInvariant = vp->IsPositionInvariant;
+ }
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ {
+ const struct gl_fragment_program *fp
+ = (const struct gl_fragment_program *) prog;
+ struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone;
+ memcpy(fpc->TexturesUsed, fp->TexturesUsed, sizeof(fp->TexturesUsed));
+ fpc->NumAluInstructions = fp->NumAluInstructions;
+ fpc->NumTexInstructions = fp->NumTexInstructions;
+ fpc->NumTexIndirections = fp->NumTexIndirections;
+ fpc->NumNativeAluInstructions = fp->NumNativeAluInstructions;
+ fpc->NumNativeTexInstructions = fp->NumNativeTexInstructions;
+ fpc->NumNativeTexIndirections = fp->NumNativeTexIndirections;
+ fpc->FogOption = fp->FogOption;
+ fpc->UsesKill = fp->UsesKill;
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
+ }
+
+ return clone;
+}
+
+
+
+/**
* Basic info about each instruction
*/
struct instruction_info
diff --git a/src/mesa/shader/program.h b/src/mesa/shader/program.h
index a3f50b9..98e2b53 100644
--- a/src/mesa/shader/program.h
+++ b/src/mesa/shader/program.h
@@ -121,6 +121,9 @@
_mesa_realloc_instructions(struct prog_instruction *oldInst,
GLuint numOldInst, GLuint numNewInst);
+extern struct gl_program *
+_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog);
+
/**
* Used for describing GL state referenced from inside ARB vertex and
@@ -203,8 +206,9 @@
*/
struct gl_program_parameter
{
- const char *Name; /**< Null-terminated string */
+ const char *Name; /**< Null-terminated string */
enum register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */
+ GLuint Size; /**< Number of components (1..4) */
/**
* A sequence of STATE_* tokens and integers to identify GL state.
*/
@@ -236,6 +240,14 @@
extern void
_mesa_free_parameter_list(struct gl_program_parameter_list *paramList);
+extern struct gl_program_parameter_list *
+_mesa_clone_parameter_list(const struct gl_program_parameter_list *list);
+
+extern GLint
+_mesa_add_parameter(struct gl_program_parameter_list *paramList,
+ const char *name, const GLfloat values[4], GLuint size,
+ enum register_file type);
+
extern GLint
_mesa_add_named_parameter(struct gl_program_parameter_list *paramList,
const char *name, const GLfloat values[4]);