/*
* Mesa 3-D graphics library
- * Version: 5.1
+ * Version: 6.0
*
- * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
}
+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;
+ }
+
+ 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
+ * 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
* \return pointer to new program object
*/
struct program *
-_mesa_alloc_program(GLcontext *ctx, GLenum target, GLuint id)
+_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
{
- struct program *prog;
+ 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 {
- _mesa_problem(ctx, "bad target in _mesa_alloc_program");
+ 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;
}
/**
* Delete a program and remove it from the hash table, ignoring the
* reference count.
- * \note Called from the GL API dispatcher.
+ * Called via ctx->Driver.DeleteProgram. May be wrapped (OO deriviation)
+ * by a device driver function.
*/
void
_mesa_delete_program(GLcontext *ctx, struct program *prog)
if (vprog->Instructions)
_mesa_free(vprog->Instructions);
}
- else if (prog->Target == GL_FRAGMENT_PROGRAM_NV) {
+ else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
+ prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
struct fragment_program *fprog = (struct fragment_program *) prog;
if (fprog->Instructions)
_mesa_free(fprog->Instructions);
idx = add_parameter(paramList, "Some State", NULL, STATE);
for (a=0; a<6; a++)
- paramList->Parameters[idx].StateIndexes[a] = stateTokens[a];
+ paramList->Parameters[idx].StateIndexes[a] = (enum state_index) stateTokens[a];
return idx;
}
{
GLuint i;
+ if (!paramList)
+ return NULL;
+
if (nameLen == -1) {
/* name is null-terminated */
for (i = 0; i < paramList->NumParameters; i++) {
{
GLint i;
+ if (!paramList)
+ return -1;
+
if (nameLen == -1) {
/* name is null-terminated */
for (i = 0; i < (GLint) paramList->NumParameters; i++) {
case STATE_LOCAL:
COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]);
break;
+ default:
+ _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+ return;
}
}
return;
case STATE_LOCAL:
COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]);
break;
+ default:
+ _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+ return;
}
}
return;
struct program_parameter_list *paramList)
{
GLuint i;
+
+ if (!paramList)
+ return;
+
for (i = 0; i < paramList->NumParameters; i++) {
if (paramList->Parameters[i].Type == STATE) {
_mesa_fetch_state(ctx, paramList->Parameters[i].StateIndexes,
* \note Called from the GL API dispatcher by both glBindProgramNV
* and glBindProgramARB.
*/
-void
+void GLAPIENTRY
_mesa_BindProgram(GLenum target, GLuint id)
{
struct program *prog;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
if ((target == GL_VERTEX_PROGRAM_NV
&& ctx->Extensions.NV_vertex_program) ||
(target == GL_VERTEX_PROGRAM_ARB
ctx->VertexProgram.Current->Base.RefCount--;
/* and delete if refcount goes below one */
if (ctx->VertexProgram.Current->Base.RefCount <= 0) {
- _mesa_delete_program(ctx, &(ctx->VertexProgram.Current->Base));
+ ctx->Driver.DeleteProgram(ctx, &(ctx->VertexProgram.Current->Base));
_mesa_HashRemove(ctx->Shared->Programs, id);
}
}
ctx->FragmentProgram.Current->Base.RefCount--;
/* and delete if refcount goes below one */
if (ctx->FragmentProgram.Current->Base.RefCount <= 0) {
- _mesa_delete_program(ctx, &(ctx->FragmentProgram.Current->Base));
+ ctx->Driver.DeleteProgram(ctx, &(ctx->FragmentProgram.Current->Base));
_mesa_HashRemove(ctx->Shared->Programs, id);
}
}
}
else {
/* allocate a new program now */
- prog = _mesa_alloc_program(ctx, target, id);
+ prog = ctx->Driver.NewProgram(ctx, target, id);
if (!prog) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
return;
if (prog)
prog->RefCount++;
+
+ if (ctx->Driver.BindProgram)
+ ctx->Driver.BindProgram(ctx, target, prog);
}
* \note Not compiled into display lists.
* \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
*/
-void
+void GLAPIENTRY
_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
{
GLint i;
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (n < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
_mesa_BindProgram(prog->Target, 0);
}
}
- else if (prog->Target == GL_FRAGMENT_PROGRAM_NV) {
+ else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
+ prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
if (ctx->FragmentProgram.Current &&
ctx->FragmentProgram.Current->Base.Id == ids[i]) {
/* unbind this currently bound program */
}
prog->RefCount--;
if (prog->RefCount <= 0) {
- _mesa_delete_program(ctx, prog);
+ 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]);
+ }
}
}
}
* \note Not compiled into display lists.
* \note Called by both glGenProgramsNV and glGenProgramsARB.
*/
-void
+void GLAPIENTRY
_mesa_GenPrograms(GLsizei n, GLuint *ids)
{
GLuint first;
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 */
* \param id is the program identifier
* \return GL_TRUE if id is a program, else GL_FALSE.
*/
-GLboolean
+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;