📄 program.c
字号:
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_ARB) /* == GL_VERTEX_PROGRAM_NV */ 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_ARB) { /* == GL_VERTEX_PROGRAM_NV */ 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_ARB || /* == 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 GLAPIENTRYglProgramCallbackMESA(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 GLAPIENTRYglGetProgramRegisterfvMESA(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_ARB: /* == 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.VertexProgram.MaxTemps) { _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.VertexProgram.MaxAttribs; i++) { const char *name = _mesa_nv_vertex_input_register_name(i); char number[10]; _mesa_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.FragmentProgram.MaxTemps) { _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.FragmentProgram.MaxAttribs; 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_RESULT_COLR]); } else if (_mesa_strcmp(reg, "o[COLH]") == 0) { /* Fragment output color */ COPY_4V(v, ctx->FragmentProgram.Machine.Outputs[FRAG_RESULT_COLH]); } else if (_mesa_strcmp(reg, "o[DEPR]") == 0) { /* Fragment output depth */ COPY_4V(v, ctx->FragmentProgram.Machine.Outputs[FRAG_RESULT_DEPR]); } else { /* try user-defined identifiers */ const GLfloat *value = _mesa_lookup_parameter_value( ctx->FragmentProgram.Current->Base.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 + -