⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shader_api.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Mesa 3-D graphics library * Version:  7.2 * * Copyright (C) 2004-2008  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"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * \file shader_api.c * Implementation of GLSL-related API functions * \author Brian Paul *//** * XXX things to do: * 1. Check that the right error code is generated for all _mesa_error() calls. * 2. Insert FLUSH_VERTICES calls in various places */#include "glheader.h"#include "context.h"#include "hash.h"#include "macros.h"#include "program.h"#include "prog_parameter.h"#include "prog_print.h"#include "prog_statevars.h"#include "prog_uniform.h"#include "shader/shader_api.h"#include "shader/slang/slang_compile.h"#include "shader/slang/slang_link.h"/** * Allocate a new gl_shader_program object, initialize it. */static struct gl_shader_program *_mesa_new_shader_program(GLcontext *ctx, GLuint name){   struct gl_shader_program *shProg;   shProg = CALLOC_STRUCT(gl_shader_program);   if (shProg) {      shProg->Type = GL_SHADER_PROGRAM_MESA;      shProg->Name = name;      shProg->RefCount = 1;      shProg->Attributes = _mesa_new_parameter_list();   }   return shProg;}/** * Clear (free) the shader program state that gets produced by linking. */void_mesa_clear_shader_program_data(GLcontext *ctx,                                struct gl_shader_program *shProg){   _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);   _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);   if (shProg->Uniforms) {      _mesa_free_uniform_list(shProg->Uniforms);      shProg->Uniforms = NULL;   }   if (shProg->Varying) {      _mesa_free_parameter_list(shProg->Varying);      shProg->Varying = NULL;   }}/** * Free all the data that hangs off a shader program object, but not the * object itself. */void_mesa_free_shader_program_data(GLcontext *ctx,                               struct gl_shader_program *shProg){   GLuint i;   assert(shProg->Type == GL_SHADER_PROGRAM_MESA);   _mesa_clear_shader_program_data(ctx, shProg);   if (shProg->Attributes) {      _mesa_free_parameter_list(shProg->Attributes);      shProg->Attributes = NULL;   }   /* detach shaders */   for (i = 0; i < shProg->NumShaders; i++) {      _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);   }   shProg->NumShaders = 0;   if (shProg->Shaders) {      _mesa_free(shProg->Shaders);      shProg->Shaders = NULL;   }   if (shProg->InfoLog) {      _mesa_free(shProg->InfoLog);      shProg->InfoLog = NULL;   }}/** * Free/delete a shader program object. */void_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg){   _mesa_free_shader_program_data(ctx, shProg);   _mesa_free(shProg);}/** * Set ptr to point to shProg. * If ptr is pointing to another object, decrement its refcount (and delete * if refcount hits zero). * Then set ptr to point to shProg, incrementing its refcount. *//* XXX this could be static */void_mesa_reference_shader_program(GLcontext *ctx,                               struct gl_shader_program **ptr,                               struct gl_shader_program *shProg){   assert(ptr);   if (*ptr == shProg) {      /* no-op */      return;   }   if (*ptr) {      /* Unreference the old shader program */      GLboolean deleteFlag = GL_FALSE;      struct gl_shader_program *old = *ptr;      ASSERT(old->RefCount > 0);      old->RefCount--;#if 0      printf("ShaderProgram %p ID=%u  RefCount-- to %d\n",             (void *) old, old->Name, old->RefCount);#endif      deleteFlag = (old->RefCount == 0);      if (deleteFlag) {         _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);         _mesa_free_shader_program(ctx, old);      }      *ptr = NULL;   }   assert(!*ptr);   if (shProg) {      shProg->RefCount++;#if 0      printf("ShaderProgram %p ID=%u  RefCount++ to %d\n",             (void *) shProg, shProg->Name, shProg->RefCount);#endif      *ptr = shProg;   }}/** * Lookup a GLSL program object. */struct gl_shader_program *_mesa_lookup_shader_program(GLcontext *ctx, GLuint name){   struct gl_shader_program *shProg;   if (name) {      shProg = (struct gl_shader_program *)         _mesa_HashLookup(ctx->Shared->ShaderObjects, name);      /* Note that both gl_shader and gl_shader_program objects are kept       * in the same hash table.  Check the object's type to be sure it's       * what we're expecting.       */      if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {         return NULL;      }      return shProg;   }   return NULL;}/** * As above, but record an error if program is not found. */static struct gl_shader_program *_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,                                const char *caller){   if (!name) {      _mesa_error(ctx, GL_INVALID_VALUE, caller);      return NULL;   }   else {      struct gl_shader_program *shProg = (struct gl_shader_program *)         _mesa_HashLookup(ctx->Shared->ShaderObjects, name);      if (!shProg) {         _mesa_error(ctx, GL_INVALID_VALUE, caller);         return NULL;      }      if (shProg->Type != GL_SHADER_PROGRAM_MESA) {         _mesa_error(ctx, GL_INVALID_OPERATION, caller);         return NULL;      }      return shProg;   }}/** * Allocate a new gl_shader object, initialize it. */struct gl_shader *_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type){   struct gl_shader *shader;   assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);   shader = CALLOC_STRUCT(gl_shader);   if (shader) {      shader->Type = type;      shader->Name = name;      shader->RefCount = 1;   }   return shader;}void_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh){   if (sh->Source)      _mesa_free((void *) sh->Source);   if (sh->InfoLog)      _mesa_free(sh->InfoLog);   _mesa_reference_program(ctx, &sh->Program, NULL);   _mesa_free(sh);}/** * Set ptr to point to sh. * If ptr is pointing to another shader, decrement its refcount (and delete * if refcount hits zero). * Then set ptr to point to sh, incrementing its refcount. *//* XXX this could be static */void_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,                       struct gl_shader *sh){   assert(ptr);   if (*ptr == sh) {      /* no-op */      return;   }   if (*ptr) {      /* Unreference the old shader */      GLboolean deleteFlag = GL_FALSE;      struct gl_shader *old = *ptr;      ASSERT(old->RefCount > 0);      old->RefCount--;      /*printf("SHADER DECR %p (%d) to %d\n",        (void*) old, old->Name, old->RefCount);*/      deleteFlag = (old->RefCount == 0);      if (deleteFlag) {         _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);         _mesa_free_shader(ctx, old);      }      *ptr = NULL;   }   assert(!*ptr);   if (sh) {      /* reference new */      sh->RefCount++;      /*printf("SHADER INCR %p (%d) to %d\n",        (void*) sh, sh->Name, sh->RefCount);*/      *ptr = sh;   }}/** * Lookup a GLSL shader object. */struct gl_shader *_mesa_lookup_shader(GLcontext *ctx, GLuint name){   if (name) {      struct gl_shader *sh = (struct gl_shader *)         _mesa_HashLookup(ctx->Shared->ShaderObjects, name);      /* Note that both gl_shader and gl_shader_program objects are kept       * in the same hash table.  Check the object's type to be sure it's       * what we're expecting.       */      if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {         return NULL;      }      return sh;   }   return NULL;}/** * As above, but record an error if shader is not found. */static struct gl_shader *_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller){   if (!name) {      _mesa_error(ctx, GL_INVALID_VALUE, caller);      return NULL;   }   else {      struct gl_shader *sh = (struct gl_shader *)         _mesa_HashLookup(ctx->Shared->ShaderObjects, name);      if (!sh) {         _mesa_error(ctx, GL_INVALID_VALUE, caller);         return NULL;      }      if (sh->Type == GL_SHADER_PROGRAM_MESA) {         _mesa_error(ctx, GL_INVALID_OPERATION, caller);         return NULL;      }      return sh;   }}/** * Initialize context's shader state. */void_mesa_init_shader_state(GLcontext * ctx){   /* Device drivers may override these to control what kind of instructions    * are generated by the GLSL compiler.    */   ctx->Shader.EmitHighLevelInstructions = GL_TRUE;   ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */   ctx->Shader.EmitComments = GL_FALSE;}/** * Free the per-context shader-related state. */void_mesa_free_shader_state(GLcontext *ctx){   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);}/** * Copy string from <src> to <dst>, up to maxLength characters, returning * length of <dst> in <length>. * \param src  the strings source * \param maxLength  max chars to copy * \param length  returns number of chars copied * \param dst  the string destination */static voidcopy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src){   GLsizei len;   for (len = 0; len < maxLength - 1 && src && src[len]; len++)      dst[len] = src[len];   if (maxLength > 0)      dst[len] = 0;   if (length)      *length = len;}static GLboolean_mesa_is_program(GLcontext *ctx, GLuint name){   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);   return shProg ? GL_TRUE : GL_FALSE;}static GLboolean_mesa_is_shader(GLcontext *ctx, GLuint name){   struct gl_shader *shader = _mesa_lookup_shader(ctx, name);   return shader ? GL_TRUE : GL_FALSE;}/** * Called via ctx->Driver.AttachShader() */static void_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader){   struct gl_shader_program *shProg;   struct gl_shader *sh;   GLuint i, n;   shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");   if (!shProg)      return;   sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");   if (!sh) {      return;   }   n = shProg->NumShaders;   for (i = 0; i < n; i++) {      if (shProg->Shaders[i] == sh) {         /* already attached */         return;      }   }   /* grow list */   shProg->Shaders = (struct gl_shader **)      _mesa_realloc(shProg->Shaders,                    n * sizeof(struct gl_shader *),                    (n + 1) * sizeof(struct gl_shader *));   if (!shProg->Shaders) {      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");      return;   }   /* append */   shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */   _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);   shProg->NumShaders++;}static GLint_mesa_get_attrib_location(GLcontext *ctx, GLuint program,                          const GLchar *name){   struct gl_shader_program *shProg      = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");   if (!shProg) {      return -1;   }   if (!shProg->LinkStatus) {      _mesa_error(ctx, GL_INVALID_OPERATION,                  "glGetAttribLocation(program not linked)");      return -1;   }   if (!name)      return -1;   if (shProg->VertexProgram) {      const struct gl_program_parameter_list *attribs =         shProg->VertexProgram->Base.Attributes;      if (attribs) {         GLint i = _mesa_lookup_parameter_index(attribs, -1, name);         if (i >= 0) {            return attribs->Parameters[i].StateIndexes[0];         }      }   }   return -1;}static void_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,                           const GLchar *name){   struct gl_shader_program *shProg;   const GLint size = -1; /* unknown size */   GLint i;   GLenum datatype = GL_FLOAT_VEC4;   shProg = _mesa_lookup_shader_program_err(ctx, program,                                            "glBindAttribLocation");   if (!shProg) {      return;   }   if (!name)      return;   if (strncmp(name, "gl_", 3) == 0) {      _mesa_error(ctx, GL_INVALID_OPERATION,                  "glBindAttribLocation(illegal name)");      return;   }   if (index >= ctx->Const.VertexProgram.MaxAttribs) {      _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");      return;   }   /* this will replace the current value if it's already in the list */   i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);   if (i < 0) {      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");      return;   }   /*    * Note that this attribute binding won't go into effect until

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -