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 + -
显示快捷键?