summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);