diff options
-rw-r--r-- | src/mesa/main/arbprogram.c | 13 | ||||
-rw-r--r-- | src/mesa/main/dd.h | 12 | ||||
-rw-r--r-- | src/mesa/main/program.c | 102 | ||||
-rw-r--r-- | src/mesa/main/program.h | 13 |
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); |