shader_api.c
来自「Mesa is an open-source implementation of」· C语言 代码 · 共 1,638 行 · 第 1/3 页
C
1,638 行
* glLinkProgram is called again. */}static GLuint_mesa_create_shader(GLcontext *ctx, GLenum type){ struct gl_shader *sh; GLuint name; name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); switch (type) { case GL_FRAGMENT_SHADER: case GL_VERTEX_SHADER: sh = _mesa_new_shader(ctx, name, type); break; default: _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)"); return 0; } _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); return name;}static GLuint _mesa_create_program(GLcontext *ctx){ GLuint name; struct gl_shader_program *shProg; name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); shProg = _mesa_new_shader_program(ctx, name); _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); assert(shProg->RefCount == 1); return name;}/** * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's * DeleteProgramARB. */static void_mesa_delete_program2(GLcontext *ctx, GLuint name){ /* * NOTE: deleting shaders/programs works a bit differently than * texture objects (and buffer objects, etc). Shader/program * handles/IDs exist in the hash table until the object is really * deleted (refcount==0). With texture objects, the handle/ID is * removed from the hash table in glDeleteTextures() while the tex * object itself might linger until its refcount goes to zero. */ struct gl_shader_program *shProg; shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram"); if (!shProg) return; shProg->DeletePending = GL_TRUE; /* effectively, decr shProg's refcount */ _mesa_reference_shader_program(ctx, &shProg, NULL);}static void_mesa_delete_shader(GLcontext *ctx, GLuint shader){ struct gl_shader *sh; sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader"); if (!sh) return; sh->DeletePending = GL_TRUE; /* effectively, decr sh's refcount */ _mesa_reference_shader(ctx, &sh, NULL);}static void_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader){ struct gl_shader_program *shProg; GLuint n; GLuint i, j; shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader"); if (!shProg) return; n = shProg->NumShaders; for (i = 0; i < n; i++) { if (shProg->Shaders[i]->Name == shader) { /* found it */ struct gl_shader **newList; /* release */ _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); /* alloc new, smaller array */ newList = (struct gl_shader **) _mesa_malloc((n - 1) * sizeof(struct gl_shader *)); if (!newList) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); return; } for (j = 0; j < i; j++) { newList[j] = shProg->Shaders[j]; } while (++i < n) newList[j++] = shProg->Shaders[i]; _mesa_free(shProg->Shaders); shProg->Shaders = newList; shProg->NumShaders = n - 1;#ifdef DEBUG /* sanity check */ { for (j = 0; j < shProg->NumShaders; j++) { assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); assert(shProg->Shaders[j]->RefCount > 0); } }#endif return; } } /* not found */ { GLenum err; if (_mesa_is_shader(ctx, shader)) err = GL_INVALID_OPERATION; else if (_mesa_is_program(ctx, shader)) err = GL_INVALID_OPERATION; else err = GL_INVALID_VALUE; _mesa_error(ctx, err, "glDetachProgram(shader)"); return; }}static GLintsizeof_glsl_type(GLenum type){ switch (type) { case GL_FLOAT: case GL_INT: case GL_BOOL: case GL_SAMPLER_1D: case GL_SAMPLER_2D: case GL_SAMPLER_3D: case GL_SAMPLER_CUBE: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: case GL_SAMPLER_2D_RECT_ARB: case GL_SAMPLER_2D_RECT_SHADOW_ARB: case GL_SAMPLER_1D_ARRAY_SHADOW_EXT: case GL_SAMPLER_2D_ARRAY_SHADOW_EXT: case GL_SAMPLER_CUBE_SHADOW_EXT: return 1; case GL_FLOAT_VEC2: case GL_INT_VEC2: case GL_BOOL_VEC2: return 2; case GL_FLOAT_VEC3: case GL_INT_VEC3: case GL_BOOL_VEC3: return 3; case GL_FLOAT_VEC4: case GL_INT_VEC4: case GL_BOOL_VEC4: return 4; case GL_FLOAT_MAT2: case GL_FLOAT_MAT2x3: case GL_FLOAT_MAT2x4: return 8; /* two float[4] vectors */ case GL_FLOAT_MAT3: case GL_FLOAT_MAT3x2: case GL_FLOAT_MAT3x4: return 12; /* three float[4] vectors */ case GL_FLOAT_MAT4: case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: return 16; /* four float[4] vectors */ default: _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()"); return 1; }}static void_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *nameOut){ const struct gl_program_parameter_list *attribs = NULL; struct gl_shader_program *shProg; shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); if (!shProg) return; if (shProg->VertexProgram) attribs = shProg->VertexProgram->Base.Attributes; if (!attribs || index >= attribs->NumParameters) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); return; } copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name); if (size) *size = attribs->Parameters[index].Size / sizeof_glsl_type(attribs->Parameters[index].DataType); if (type) *type = attribs->Parameters[index].DataType;}/** * Called via ctx->Driver.GetActiveUniform(). */static void_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *nameOut){ const struct gl_shader_program *shProg; const struct gl_program *prog; GLint progPos; shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); if (!shProg) return; if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); return; } progPos = shProg->Uniforms->Uniforms[index].VertPos; if (progPos >= 0) { prog = &shProg->VertexProgram->Base; } else { progPos = shProg->Uniforms->Uniforms[index].FragPos; if (progPos >= 0) { prog = &shProg->FragmentProgram->Base; } } if (!prog || progPos < 0) return; /* should never happen */ if (nameOut) copy_string(nameOut, maxLength, length, prog->Parameters->Parameters[progPos].Name); if (size) *size = prog->Parameters->Parameters[progPos].Size / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType); if (type) *type = prog->Parameters->Parameters[progPos].DataType;}/** * Called via ctx->Driver.GetAttachedShaders(). */static void_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj){ struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders"); if (shProg) { GLuint i; for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) { obj[i] = shProg->Shaders[i]->Name; } if (count) *count = i; }}static GLuint_mesa_get_handle(GLcontext *ctx, GLenum pname){#if 0 GET_CURRENT_CONTEXT(ctx); switch (pname) { case GL_PROGRAM_OBJECT_ARB: { struct gl2_program_intf **pro = ctx->Shader.CurrentProgram; if (pro != NULL) return (**pro)._container._generic. GetName((struct gl2_generic_intf **) (pro)); } break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB"); }#endif return 0;}static void_mesa_get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params){ const struct gl_program_parameter_list *attribs; struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program); if (!shProg) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)"); return; } if (shProg->VertexProgram) attribs = shProg->VertexProgram->Base.Attributes; else attribs = NULL; switch (pname) { case GL_DELETE_STATUS: *params = shProg->DeletePending; break; case GL_LINK_STATUS: *params = shProg->LinkStatus; break; case GL_VALIDATE_STATUS: *params = shProg->Validated; break; case GL_INFO_LOG_LENGTH: *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0; break; case GL_ATTACHED_SHADERS: *params = shProg->NumShaders; break; case GL_ACTIVE_ATTRIBUTES: *params = attribs ? attribs->NumParameters : 0; break; case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1; break; case GL_ACTIVE_UNIFORMS: *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0; break; case GL_ACTIVE_UNIFORM_MAX_LENGTH: *params = _mesa_longest_uniform_name(shProg->Uniforms); if (*params > 0) (*params)++; /* add one for terminating zero */ break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)"); return; }}static void_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params){ struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv"); if (!shader) { return; } switch (pname) { case GL_SHADER_TYPE: *params = shader->Type; break; case GL_DELETE_STATUS: *params = shader->DeletePending; break; case GL_COMPILE_STATUS: *params = shader->CompileStatus; break; case GL_INFO_LOG_LENGTH: *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0; break; case GL_SHADER_SOURCE_LENGTH: *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)"); return; }}static void_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog){ struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program); if (!shProg) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)"); return; } copy_string(infoLog, bufSize, length, shProg->InfoLog);}static void_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog){ struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); if (!sh) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)"); return; } copy_string(infoLog, bufSize, length, sh->InfoLog);}/** * Called via ctx->Driver.GetShaderSource(). */static void_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *sourceOut){ struct gl_shader *sh; sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource"); if (!sh) { return; } copy_string(sourceOut, maxLength, length, sh->Source);}#define MAX_UNIFORM_ELEMENTS 16/** * Helper for GetUniformfv(), GetUniformiv() * Returns number of elements written to 'params' output. */static GLuintget_uniformfv(GLcontext *ctx, GLuint program, GLint location, GLfloat *params){ struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program); if (shProg) { if (shProg->Uniforms && location >= 0 && location < (GLint) shProg->Uniforms->NumUniforms) { GLint progPos; GLuint i; const struct gl_program *prog = NULL; progPos = shProg->Uniforms->Uniforms[location].VertPos; if (progPos >= 0) { prog = &shProg->VertexProgram->Base; } else { progPos = shProg->Uniforms->Uniforms[location].FragPos; if (progPos >= 0) { prog = &shProg->FragmentProgram->Base; } } ASSERT(prog); if (prog) { /* See uniformiv() below */ assert(prog->Parameters->Parameters[progPos].Size <= MAX_UNIFORM_ELEMENTS); for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) { params[i] = prog->Parameters->ParameterValues[progPos][i]; } return prog->Parameters->Parameters[progPos].Size; } } else { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)"); } } else { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)"); } return 0;}/** * Called via ctx->Driver.GetUniformfv(). */static void_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location, GLfloat *params){ (void) get_uniformfv(ctx, program, location, params);}/** * Called via ctx->Driver.GetUniformiv(). */static void_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location, GLint *params){ GLfloat fparams[MAX_UNIFORM_ELEMENTS]; GLuint n = get_uniformfv(ctx, program, location, fparams); GLuint i; assert(n <= MAX_UNIFORM_ELEMENTS); for (i = 0; i < n; i++) { params[i] = (GLint) fparams[i]; }}/** * Called via ctx->Driver.GetUniformLocation(). */static GLint_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name){ struct gl_shader_program *shProg =
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?