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.
This commit is contained in:
Keith Whitwell 2004-02-14 15:00:42 +00:00
parent 70dacabfe5
commit 964e5325bd
4 changed files with 97 additions and 43 deletions

View file

@ -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;
/*

View file

@ -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);
/*@}*/

View file

@ -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;

View file

@ -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);