📄 program.c
字号:
{
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,
paramList->ParameterValues[i]);
}
}
}
/**********************************************************************/
/* API functions */
/**********************************************************************/
/**
* Bind a program (make it current)
* \note Called from the GL API dispatcher by both glBindProgramNV
* and glBindProgramARB.
*/
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->Extensions.ARB_vertex_program)) {
/*** Vertex program binding ***/
struct vertex_program *curProg = ctx->VertexProgram.Current;
if (curProg->Base.Id == id) {
/* binding same program - no change */
return;
}
if (curProg->Base.Id != 0) {
/* decrement refcount on previously bound vertex program */
curProg->Base.RefCount--;
/* and delete if refcount goes below one */
if (curProg->Base.RefCount <= 0) {
/* the program ID was already removed from the hash table */
ctx->Driver.DeleteProgram(ctx, &(curProg->Base));
}
}
}
else if ((target == GL_FRAGMENT_PROGRAM_NV
&& ctx->Extensions.NV_fragment_program) ||
(target == GL_FRAGMENT_PROGRAM_ARB
&& ctx->Extensions.ARB_fragment_program)) {
/*** Fragment program binding ***/
struct fragment_program *curProg = ctx->FragmentProgram.Current;
if (curProg->Base.Id == id) {
/* binding same program - no change */
return;
}
if (curProg->Base.Id != 0) {
/* decrement refcount on previously bound fragment program */
curProg->Base.RefCount--;
/* and delete if refcount goes below one */
if (curProg->Base.RefCount <= 0) {
/* the program ID was already removed from the hash table */
ctx->Driver.DeleteProgram(ctx, &(curProg->Base));
}
}
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
return;
}
/* NOTE: binding to a non-existant program is not an error.
* That's supposed to be caught in glBegin.
*/
if (id == 0) {
/* Bind default program */
prog = NULL;
if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB)
prog = ctx->Shared->DefaultVertexProgram;
else
prog = ctx->Shared->DefaultFragmentProgram;
}
else {
/* Bind user program */
prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
if (!prog || prog == &_mesa_DummyProgram) {
/* allocate a new program now */
prog = ctx->Driver.NewProgram(ctx, target, id);
if (!prog) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
return;
}
_mesa_HashInsert(ctx->Shared->Programs, id, prog);
}
else if (prog->Target != target) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBindProgramNV/ARB(target mismatch)");
return;
}
}
/* bind now */
if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB) {
ctx->VertexProgram.Current = (struct vertex_program *) prog;
}
else if (target == GL_FRAGMENT_PROGRAM_NV || target == GL_FRAGMENT_PROGRAM_ARB) {
ctx->FragmentProgram.Current = (struct fragment_program *) prog;
}
/* Never null pointers */
ASSERT(ctx->VertexProgram.Current);
ASSERT(ctx->FragmentProgram.Current);
if (prog)
prog->RefCount++;
if (ctx->Driver.BindProgram)
ctx->Driver.BindProgram(ctx, target, prog);
}
/**
* Delete a list of programs.
* \note Not compiled into display lists.
* \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
*/
void GLAPIENTRY
_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
{
GLint i;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (n < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
return;
}
for (i = 0; i < n; i++) {
if (ids[i] != 0) {
struct program *prog = (struct program *)
_mesa_HashLookup(ctx->Shared->Programs, ids[i]);
if (prog == &_mesa_DummyProgram) {
_mesa_HashRemove(ctx->Shared->Programs, ids[i]);
}
else if (prog) {
/* Unbind program if necessary */
if (prog->Target == GL_VERTEX_PROGRAM_NV ||
prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
if (ctx->VertexProgram.Current &&
ctx->VertexProgram.Current->Base.Id == ids[i]) {
/* unbind this currently bound program */
_mesa_BindProgram(prog->Target, 0);
}
}
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 */
_mesa_BindProgram(prog->Target, 0);
}
}
else {
_mesa_problem(ctx, "bad target in glDeleteProgramsNV");
return;
}
/* The ID is immediately available for re-use now */
_mesa_HashRemove(ctx->Shared->Programs, ids[i]);
prog->RefCount--;
if (prog->RefCount <= 0) {
ctx->Driver.DeleteProgram(ctx, prog);
}
}
}
}
}
/**
* Generate a list of new program identifiers.
* \note Not compiled into display lists.
* \note Called by both glGenProgramsNV and glGenProgramsARB.
*/
void GLAPIENTRY
_mesa_GenPrograms(GLsizei n, GLuint *ids)
{
GLuint first;
GLuint i;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (n < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
return;
}
if (!ids)
return;
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
/* Insert pointer to dummy program as placeholder */
for (i = 0; i < (GLuint) n; i++) {
_mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
}
/* Return the program names */
for (i = 0; i < (GLuint) n; i++) {
ids[i] = first + i;
}
}
/**
* Determine if id names a vertex or fragment program.
* \note Not compiled into display lists.
* \note Called from both glIsProgramNV and glIsProgramARB.
* \param id is the program identifier
* \return GL_TRUE if id is a program, else GL_FALSE.
*/
GLboolean GLAPIENTRY
_mesa_IsProgram(GLuint id)
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
if (id == 0)
return GL_FALSE;
if (_mesa_HashLookup(ctx->Shared->Programs, id))
return GL_TRUE;
else
return GL_FALSE;
}
/**********************************************************************/
/* GL_MESA_program_debug extension */
/**********************************************************************/
/* XXX temporary */
GLAPI void GLAPIENTRY
glProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
GLvoid *data)
{
_mesa_ProgramCallbackMESA(target, callback, data);
}
void
_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
GLvoid *data)
{
GET_CURRENT_CONTEXT(ctx);
switch (target) {
case GL_FRAGMENT_PROGRAM_ARB:
if (!ctx->Extensions.ARB_fragment_program) {
_mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
return;
}
ctx->FragmentProgram.Callback = callback;
ctx->FragmentProgram.CallbackData = data;
break;
case GL_FRAGMENT_PROGRAM_NV:
if (!ctx->Extensions.NV_fragment_program) {
_mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
return;
}
ctx->FragmentProgram.Callback = callback;
ctx->FragmentProgram.CallbackData = data;
break;
case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
if (!ctx->Extensions.ARB_vertex_program &&
!ctx->Extensions.NV_vertex_program) {
_mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
return;
}
ctx->VertexProgram.Callback = callback;
ctx->VertexProgram.CallbackData = data;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
return;
}
}
/* XXX temporary */
GLAPI void GLAPIENTRY
glGetProgramRegisterfvMESA(GLenum target,
GLsizei len, const GLubyte *registerName,
GLfloat *v)
{
_mesa_GetProgramRegisterfvMESA(target, len, registerName, v);
}
void
_mesa_GetProgramRegisterfvMESA(GLenum target,
GLsizei len, const GLubyte *registerName,
GLfloat *v)
{
char reg[1000];
GET_CURRENT_CONTEXT(ctx);
/* We _should_ be inside glBegin/glEnd */
#if 0
if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA");
return;
}
#endif
/* make null-terminated copy of registerName */
len = MIN2((unsigned int) len, sizeof(reg) - 1);
_mesa_memcpy(reg, registerName, len);
reg[len] = 0;
switch (target) {
case GL_VERTEX_PROGRAM_NV:
if (!ctx->Extensions.ARB_vertex_program &&
!ctx->Extensions.NV_vertex_program) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetProgramRegisterfvMESA(target)");
return;
}
if (!ctx->VertexProgram._Enabled) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetProgramRegisterfvMESA");
return;
}
/* GL_NV_vertex_program */
if (reg[0] == 'R') {
/* Temp register */
GLint i = _mesa_atoi(reg + 1);
if (i >= (GLint)ctx->Const.MaxVertexProgramTemps) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetProgramRegisterfvMESA(registerName)");
return;
}
COPY_4V(v, ctx->VertexProgram.Temporaries[i]);
}
else if (reg[0] == 'v' && reg[1] == '[') {
/* Vertex Input attribute */
GLuint i;
for (i = 0; i < ctx->Const.MaxVertexProgramAttribs; i++) {
const char *name = _mesa_nv_vertex_input_register_name(i);
char number[10];
sprintf(number, "%d", i);
if (_mesa_strncmp(reg + 2, name, 4) == 0 ||
_mesa_strncmp(reg + 2, number, _mesa_strlen(number)) == 0) {
COPY_4V(v, ctx->VertexProgram.Inputs[i]);
return;
}
}
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetProgramRegisterfvMESA(registerName)");
return;
}
else if (reg[0] == 'o' && reg[1] == '[') {
/* Vertex output attribute */
}
/* GL_ARB_vertex_program */
else if (_mesa_strncmp(reg, "vertex.", 7) == 0) {
}
else {
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetProgramRegisterfvMESA(registerName)");
return;
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
if (!ctx->Extensions.ARB_fragment_program) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetProgramRegisterfvMESA(target)");
return;
}
if (!ctx->FragmentProgram._Enabled) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetProgramRegisterfvMESA");
return;
}
/* XXX to do */
break;
case GL_FRAGMENT_PROGRAM_NV:
if (!ctx->Extensions.NV_fragment_program) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetProgramRegisterfvMESA(target)");
return;
}
if (!ctx->FragmentProgram._Enabled) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetProgramRegisterfvMESA");
return;
}
if (reg[0] == 'R') {
/* Temp register */
GLint i = _mesa_atoi(reg + 1);
if (i >= (GLint)ctx->Const.MaxFragmentProgramTemps) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetProgramRegisterfvMESA(registerName)");
return;
}
COPY_4V(v, ctx->FragmentProgram.Machine.Temporaries[i]);
}
else if (reg[0] == 'f' && reg[1] == '[') {
/* Fragment input attribute */
GLuint i;
for (i = 0; i < ctx->Const.MaxFragmentProgramAttribs; i++) {
const char *name = _mesa_nv_fragment_input_register_name(i);
if (_mesa_strncmp(reg + 2, name, 4) == 0) {
COPY_4V(v, ctx->FragmentProgram.Machine.Inputs[i]);
return;
}
}
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetProgramRegisterfvMESA(registerName)");
return;
}
else if (_mesa_strcmp(reg, "o[COLR]") == 0) {
/* Fragment output color */
COPY_4V(v, ctx->FragmentProgram.Machine.Outputs[FRAG_OUTPUT_COLR]);
}
else if (_mesa_strcmp(reg, "o[COLH]") == 0) {
/* Fragment output color */
COPY_4V(v, ctx->FragmentProgram.Machine.Outputs[FRAG_OUTPUT_COLH]);
}
else if (_mesa_strcmp(reg, "o[DEPR]") == 0) {
/* Fragment output depth */
COPY_4V(v, ctx->FragmentProgram.Machine.Outputs[FRAG_OUTPUT_DEPR]);
}
else {
/* try user-defined identifiers */
const GLfloat *value = _mesa_lookup_parameter_value(
ctx->FragmentProgram.Current->Parameters, -1, reg);
if (value) {
COPY_4V(v, value);
}
else {
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetProgramRegisterfvMESA(registerName)");
return;
}
}
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetProgramRegisterfvMESA(target)");
return;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -