summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2004-02-14 15:00:42 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2004-02-14 15:00:42 +0000
commit964e5325bdcca702cfb2f210e0b89809e42847ef (patch)
tree1d65322fce17d62024ad7f900c30a48e7bbb321c
parent70dacabfe503e89d8c4a8df9fa6568aa5613a25b (diff)
Make it easier for drivers to create "subclasses" of the existing
program struct hierarchy. Add driver callbacks to enable the above and make it possible to track more changes to program objects.
-rw-r--r--src/mesa/main/arbprogram.c13
-rw-r--r--src/mesa/main/dd.h12
-rw-r--r--src/mesa/main/program.c102
-rw-r--r--src/mesa/main/program.h13
4 files changed, 97 insertions, 43 deletions
diff --git a/src/mesa/main/arbprogram.c b/src/mesa/main/arbprogram.c
index ab27e086770..f6d16b5547f 100644
--- a/src/mesa/main/arbprogram.c
+++ b/src/mesa/main/arbprogram.c
@@ -202,6 +202,9 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
}
_mesa_parse_arb_vertex_program(ctx, target, (const GLubyte *) string,
len, prog);
+
+ if (ctx->Driver.ProgramStringNotify)
+ ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
}
else if (target == GL_FRAGMENT_PROGRAM_ARB
&& ctx->Extensions.ARB_fragment_program) {
@@ -212,9 +215,13 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
}
_mesa_parse_arb_fragment_program(ctx, target, (const GLubyte *) string,
len, prog);
+
+ if (ctx->Driver.ProgramStringNotify)
+ ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
+ return;
}
}
@@ -618,8 +625,10 @@ _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
*params = ctx->Const.MaxFragmentProgramEnvParams;
break;
case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
- /* XXX ok? */
- *params = GL_TRUE;
+ if (ctx->Driver.IsProgramNative)
+ *params = ctx->Driver.IsProgramNative( ctx, target, prog );
+ else
+ *params = GL_TRUE;
break;
/*
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index f9fdd3b92b6..f1b49b7a300 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -572,7 +572,17 @@ struct dd_function_table {
/** Allocate a new program */
struct program * (*NewProgram)(GLcontext *ctx, GLenum target, GLuint id);
/** Delete a program */
- void (*DeleteProgram)(GLcontext *ctx, struct program *prog);
+ void (*DeleteProgram)(GLcontext *ctx, struct program *prog);
+ /** Notify driver that a program string has been specified. */
+ void (*ProgramStringNotify)(GLcontext *ctx, GLenum target,
+ struct program *prog);
+
+
+
+ /** Query if program can be loaded onto hardware */
+ GLboolean (*IsProgramNative)(GLcontext *ctx, GLenum target,
+ struct program *prog);
+
/*@}*/
diff --git a/src/mesa/main/program.c b/src/mesa/main/program.c
index e32e8a3b1ac..fe536566304 100644
--- a/src/mesa/main/program.c
+++ b/src/mesa/main/program.c
@@ -138,12 +138,49 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
}
+static struct program * _mesa_init_program_struct( GLcontext *ctx,
+ struct program *prog,
+ GLenum target, GLuint id)
+{
+ if (prog) {
+ prog->Id = id;
+ prog->Target = target;
+ prog->Resident = GL_TRUE;
+ prog->RefCount = 1;
+ }
+
+ fprintf(stderr, "%s %x %x\n", __FUNCTION__, target, prog);
+ return prog;
+}
+
+struct program * _mesa_init_fragment_program( GLcontext *ctx,
+ struct fragment_program *prog,
+ GLenum target, GLuint id)
+{
+ if (prog)
+ return _mesa_init_program_struct( ctx, &prog->Base, target, id );
+ else
+ return NULL;
+}
+
+struct program * _mesa_init_vertex_program( GLcontext *ctx,
+ struct vertex_program *prog,
+ GLenum target, GLuint id)
+{
+ if (prog)
+ return _mesa_init_program_struct( ctx, &prog->Base, target, id );
+ else
+ return NULL;
+}
+
/**
- * Allocate and initialize a new fragment/vertex program object but don't
- * put it into the program hash table.
- * Called via ctx->Driver.NewProgram. May be wrapped (OO deriviation)
- * by a device driver function.
+ * Allocate and initialize a new fragment/vertex program object but
+ * don't put it into the program hash table. Called via
+ * ctx->Driver.NewProgram. May be overridden (ie. replaced) by a
+ * device driver function to implement OO deriviation with additional
+ * types not understood by this function.
+ *
* \param ctx context
* \param id program id/number
* \param target program target/type
@@ -152,33 +189,21 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
struct program *
_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
{
- struct program *prog;
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
+ return _mesa_init_vertex_program( ctx, CALLOC_STRUCT(vertex_program),
+ target, id );
- if (target == GL_VERTEX_PROGRAM_NV
- || target == GL_VERTEX_PROGRAM_ARB) {
- struct vertex_program *vprog = CALLOC_STRUCT(vertex_program);
- if (!vprog) {
- return NULL;
- }
- prog = &(vprog->Base);
- }
- else if (target == GL_FRAGMENT_PROGRAM_NV
- || target == GL_FRAGMENT_PROGRAM_ARB) {
- struct fragment_program *fprog = CALLOC_STRUCT(fragment_program);
- if (!fprog) {
- return NULL;
- }
- prog = &(fprog->Base);
- }
- else {
+ case GL_FRAGMENT_PROGRAM_NV:
+ case GL_FRAGMENT_PROGRAM_ARB:
+ return _mesa_init_fragment_program( ctx, CALLOC_STRUCT(fragment_program),
+ target, id );
+
+ default:
_mesa_problem(ctx, "bad target in _mesa_new_program");
return NULL;
}
- prog->Id = id;
- prog->Target = target;
- prog->Resident = GL_TRUE;
- prog->RefCount = 1;
- return prog;
}
@@ -946,6 +971,14 @@ _mesa_DeletePrograms(GLsizei n, const GLuint *ids)
ctx->Driver.DeleteProgram(ctx, prog);
}
}
+ else {
+ /* This is necessary as we can't tell from HashLookup
+ * whether the entry exists with data == 0, or if it
+ * doesn't exist at all. As GenPrograms creates the first
+ * case below, need to call Remove() to avoid memory leak:
+ */
+ _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
+ }
}
}
}
@@ -975,16 +1008,7 @@ _mesa_GenPrograms(GLsizei n, GLuint *ids)
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
for (i = 0; i < (GLuint) n; i++) {
- const int bytes = MAX2(sizeof(struct vertex_program),
- sizeof(struct fragment_program));
- struct program *prog = (struct program *) _mesa_calloc(bytes);
- if (!prog) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPrograms");
- return;
- }
- prog->RefCount = 1;
- prog->Id = first + i;
- _mesa_HashInsert(ctx->Shared->Programs, first + i, prog);
+ _mesa_HashInsert(ctx->Shared->Programs, first + i, 0);
}
/* Return the program names */
@@ -1004,15 +1028,13 @@ _mesa_GenPrograms(GLsizei n, GLuint *ids)
GLboolean GLAPIENTRY
_mesa_IsProgram(GLuint id)
{
- struct program *prog;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
if (id == 0)
return GL_FALSE;
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
- if (prog && prog->Target)
+ if (_mesa_HashLookup(ctx->Shared->Programs, id))
return GL_TRUE;
else
return GL_FALSE;
diff --git a/src/mesa/main/program.h b/src/mesa/main/program.h
index 0217a00487d..f71b46f1f70 100644
--- a/src/mesa/main/program.h
+++ b/src/mesa/main/program.h
@@ -58,6 +58,19 @@ extern const GLubyte *
_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
GLint *line, GLint *col);
+
+extern struct program *
+_mesa_init_vertex_program( GLcontext *ctx,
+ struct vertex_program *prog,
+ GLenum target,
+ GLuint id );
+
+extern struct program *
+_mesa_init_fragment_program( GLcontext *ctx,
+ struct fragment_program *prog,
+ GLenum target,
+ GLuint id );
+
extern struct program *
_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id);