Esempio n. 1
0
void
_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
                        GLsizei maxLength, GLsizei *length, GLint *size,
                        GLenum *type, GLchar *nameOut)
{
   static const GLenum vec_types[] = {
      GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
   };
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);
   GLint sz;

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib");
      return;
   }

   if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
      return;
   }

   copy_string(nameOut, maxLength, length,
               shProg->Attributes->Parameters[index].Name);
   sz = shProg->Attributes->Parameters[index].Size;
   if (size)
      *size = 1;   /* attributes may not be arrays */
   if (type && sz > 0 && sz <= 4)  /* XXX this is a temporary hack */
      *type = vec_types[sz - 1];
}
Esempio n. 2
0
GLint
_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
                          const GLchar *name)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
      return -1;
   }

   if (!shProg->LinkStatus) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetAttribLocation(program not linked)");
      return -1;
   }

   if (!name)
      return -1;

   if (shProg->Attributes) {
      GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
      if (i >= 0) {
         return shProg->Attributes->Parameters[i].StateIndexes[0];
      }
   }
   return -1;
}
Esempio n. 3
0
/**
 * Called via ctx->Driver.UseProgram()
 */
void
_mesa_use_program(GLcontext *ctx, GLuint program)
{
   struct gl_shader_program *shProg;

   if (ctx->Shader.CurrentProgram &&
       ctx->Shader.CurrentProgram->Name == program) {
      /* no-op */
      return;
   }

   FLUSH_VERTICES(ctx, _NEW_PROGRAM);

   if (program) {
      shProg = _mesa_lookup_shader_program(ctx, program);
      if (!shProg) {
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glUseProgramObjectARB(programObj)");
         return;
      }
   }
   else {
      shProg = NULL;
   }

   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
}
Esempio n. 4
0
void
_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);
   GLuint n;
   GLuint i, j;

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glDetachShader(bad program or shader name)");
      return;
   }

   n = shProg->NumShaders;

   for (i = 0; i < n; i++) {
      if (shProg->Shaders[i]->Name == shader) {
         /* found it */
         struct gl_shader **newList;

         /* derefernce */
         _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 */
   _mesa_error(ctx, GL_INVALID_VALUE,
               "glDetachShader(shader not found)");
}
Esempio n. 5
0
void
_mesa_validate_program(GLcontext *ctx, GLuint program)
{
   struct gl_shader_program *shProg;
   shProg = _mesa_lookup_shader_program(ctx, program);
   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
      return;
   }
   /* XXX temporary */
   shProg->Validated = GL_TRUE;

   /* From the GL spec:
     any two active samplers in the current program object are of
     different types, but refer to the same texture image unit,

     any active sampler in the current program object refers to a texture
     image unit where fixed-function fragment processing accesses a
     texture target that does not match the sampler type, or 

     the sum of the number of active samplers in the program and the
     number of texture image units enabled for fixed-function fragment
     processing exceeds the combined limit on the total number of texture
     image units allowed.
   */
}
Esempio n. 6
0
/**
 * Get info about the vertex shader's outputs which are to be written
 * to the feedback buffer(s).
 */
void GLAPIENTRY
_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
                                  GLsizei bufSize, GLsizei *length,
                                  GLsizei *size, GLenum *type, GLchar *name)
{
   const struct gl_shader_program *shProg;
   const struct gl_transform_feedback_info *linked_xfb_info;
   GET_CURRENT_CONTEXT(ctx);

   shProg = _mesa_lookup_shader_program(ctx, program);
   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glGetTransformFeedbackVarying(program=%u)", program);
      return;
   }

   linked_xfb_info = &shProg->LinkedTransformFeedback;
   if (index >= (GLuint) linked_xfb_info->NumVarying) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glGetTransformFeedbackVarying(index=%u)", index);
      return;
   }

   /* return the varying's name and length */
   _mesa_copy_string(name, bufSize, length,
		     linked_xfb_info->Varyings[index].Name);

   /* return the datatype and value's size (in datatype units) */
   if (type)
      *type = linked_xfb_info->Varyings[index].Type;
   if (size)
      *size = linked_xfb_info->Varyings[index].Size;
}
Esempio n. 7
0
/**
 * Helper for GetUniformfv(), GetUniformiv()
 * Returns number of elements written to 'params' output.
 */
static GLuint
get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
              GLfloat *params)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);
   if (shProg) {
      GLint i;
      if (location >= 0 && location < shProg->Uniforms->NumParameters) {
         GLuint uSize;
         GLenum uType;
         GLint rows = 0;
         uType = shProg->Uniforms->Parameters[location].DataType;
         uSize = sizeof_glsl_type(uType);
         /* Matrix types need special handling, because they span several
          * parameters, and may also not be fully packed.
          */
         switch (shProg->Uniforms->Parameters[location].DataType) {
            case GL_FLOAT_MAT2:
            case GL_FLOAT_MAT3x2:
            case GL_FLOAT_MAT4x2:
               rows = 2;
               break;
            case GL_FLOAT_MAT2x3:
            case GL_FLOAT_MAT3:
            case GL_FLOAT_MAT4x3:
               rows = 3;
               break;
            case GL_FLOAT_MAT2x4:
            case GL_FLOAT_MAT3x4:
            case GL_FLOAT_MAT4:
               rows = 4;
         }
         if (rows != 0) {
            GLint r, c;
            for (c = 0, i = 0; c * 4 < uSize; c++)
               for (r = 0; r < rows; r++, i++)
                  params[i] = shProg->Uniforms->ParameterValues[location + c][r];
            return i;
         }
         else {
            for (i = 0; i < uSize; i++) {
               params[i] = shProg->Uniforms->ParameterValues[location][i];
            }
            return i;
         }
      }
      else {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
      }
   }
   else {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
   }
   return 0;
}
Esempio n. 8
0
static void
get_program_info_log(struct gl_context *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;
   }
   _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog);
}
Esempio n. 9
0
static void
shader_error(struct gl_context *ctx, struct gl_program *prog, const char *msg)
{
   struct gl_shader_program *shader;

   shader = _mesa_lookup_shader_program(ctx, prog->Id);

   if (shader) {
      ralloc_strcat(&shader->InfoLog, msg);
      shader->LinkStatus = GL_FALSE;
   }
}
Esempio n. 10
0
void
_mesa_get_programiv(GLcontext *ctx, GLuint program,
                    GLenum pname, GLint *params)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
      return;
   }

   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 = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
      break;
   case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
      *params = _mesa_longest_parameter_name(shProg->Attributes,
                                             PROGRAM_INPUT) + 1;
      break;
   case GL_ACTIVE_UNIFORMS:
      *params
         = _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_UNIFORM)
         + _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_SAMPLER);
      break;
   case GL_ACTIVE_UNIFORM_MAX_LENGTH:
      *params = MAX2(
             _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_UNIFORM),
             _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_SAMPLER));
      if (*params > 0)
         (*params)++;  /* add one for terminating zero */
      break;
   default:
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
      return;
   }
}
Esempio n. 11
0
/**
 * Called via ctx->Driver.LinkProgram()
 */
void
_mesa_link_program(GLcontext *ctx, GLuint program)
{
   struct gl_shader_program *shProg;

   shProg = _mesa_lookup_shader_program(ctx, program);
   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
      return;
   }

   _slang_link(ctx, program, shProg);
}
Esempio n. 12
0
static void
shader_error(GLcontext *ctx, struct gl_program *prog, const char *msg)
{
    struct gl_shader_program *shader;

    shader = _mesa_lookup_shader_program(ctx, prog->Id);

    if (shader) {
        if (shader->InfoLog) {
            free(shader->InfoLog);
        }
        shader->InfoLog = _mesa_strdup(msg);
        shader->LinkStatus = GL_FALSE;
    }
}
Esempio n. 13
0
/**
 * Called via ctx->Driver.GetShaderSource().
 */
void
_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
                        GLsizei *length, GLchar *sourceOut)
{
   struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
   if (!sh) {
      GLenum err;
      if (_mesa_lookup_shader_program(ctx, shader))
         err = GL_INVALID_OPERATION;
      else
         err = GL_INVALID_VALUE;
      _mesa_error(ctx, err, "glGetShaderSource(shader)");
      return;
   }
   copy_string(sourceOut, maxLength, length, sh->Source);
}
Esempio n. 14
0
/**
 * Called via ctx->Driver.GetAttachedShaders().
 */
void
_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
                           GLsizei *count, GLuint *obj)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);
   if (shProg) {
      GLint i;
      for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
         obj[i] = shProg->Shaders[i]->Name;
      }
      if (count)
         *count = i;
   }
   else {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
   }
}
Esempio n. 15
0
void
_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
                           const GLchar *name)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);
   const GLint size = -1; /* unknown size */
   GLint i, oldIndex;

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
      return;
   }

   if (!name)
      return;

   if (strncmp(name, "gl_", 3) == 0) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glBindAttribLocation(illegal name)");
      return;
   }

   if (shProg->LinkStatus) {
      /* get current index/location for the attribute */
      oldIndex = _mesa_get_attrib_location(ctx, program, name);
   }
   else {
      oldIndex = -1;
   }

   /* this will replace the current value if it's already in the list */
   i = _mesa_add_attribute(shProg->Attributes, name, size, index);
   if (i < 0) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
   }

   if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
      /* If the index changed, need to search/replace references to that attribute
       * in the vertex program.
       */
      _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
   }
}
Esempio n. 16
0
/**
 * Called via ctx->Driver.GetActiveUniform().
 */
void
_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
                         GLsizei maxLength, GLsizei *length, GLint *size,
                         GLenum *type, GLchar *nameOut)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);
   GLuint ind, j;

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
      return;
   }

   if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
      return;
   }

   ind = 0;
   for (j = 0; j < shProg->Uniforms->NumParameters; j++) {
      if (shProg->Uniforms->Parameters[j].Type == PROGRAM_UNIFORM ||
          shProg->Uniforms->Parameters[j].Type == PROGRAM_SAMPLER) {
         if (ind == index) {
            GLuint uSize = shProg->Uniforms->Parameters[j].Size;
            GLenum uType = shProg->Uniforms->Parameters[j].DataType;
            /* found it */
            copy_string(nameOut, maxLength, length,
                        shProg->Uniforms->Parameters[j].Name);
            if (size) {
               /* convert from floats to 'type' (eg: sizeof(mat4x4)=1) */
               *size = uSize / sizeof_glsl_type(uType);
            }
            if (type)
               *type = uType;
            return;
         }
         ind++;
      }
   }

   _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
}
Esempio n. 17
0
/**
 * For GL_EXT_separate_shader_objects
 */
GLuint GLAPIENTRY
_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string)
{
   GET_CURRENT_CONTEXT(ctx);
   const GLuint shader = create_shader(ctx, type);
   GLuint program = 0;

   if (shader) {
      shader_source(ctx, shader, _mesa_strdup(string));
      compile_shader(ctx, shader);

      program = create_shader_program(ctx);
      if (program) {
	 struct gl_shader_program *shProg;
	 struct gl_shader *sh;
	 GLint compiled = GL_FALSE;

	 shProg = _mesa_lookup_shader_program(ctx, program);
	 sh = _mesa_lookup_shader(ctx, shader);

	 get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
	 if (compiled) {
	    attach_shader(ctx, program, shader);
	    link_program(ctx, program);
	    detach_shader(ctx, program, shader);

#if 0
	    /* Possibly... */
	    if (active-user-defined-varyings-in-linked-program) {
	       append-error-to-info-log;
	       shProg->LinkStatus = GL_FALSE;
	    }
#endif
	 }

	 ralloc_strcat(&shProg->InfoLog, sh->InfoLog);
      }

      delete_shader(ctx, shader);
   }

   return program;
}
Esempio n. 18
0
/**
 * Called via ctx->Driver.ShaderSource()
 */
void
_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
{
   struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
   if (!sh) {
      GLenum err;
      if (_mesa_lookup_shader_program(ctx, shader))
         err = GL_INVALID_OPERATION;
      else
         err = GL_INVALID_VALUE;
      _mesa_error(ctx, err, "glShaderSource(shaderObj)");
      return;
   }

   /* free old shader source string and install new one */
   if (sh->Source) {
      _mesa_free((void *) sh->Source);
   }
   sh->Source = source;
   sh->CompileStatus = GL_FALSE;
}
Esempio n. 19
0
/**
 * Called via ctx->Driver.AttachShader()
 */
void
_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);
   struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
   GLuint n;
   GLuint i;

   if (!shProg || !sh) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glAttachShader(bad program or shader name)");
      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++;
}
Esempio n. 20
0
/**
 * Get info about the transform feedback outputs which are to be written
 * to the feedback buffer(s).
 */
void GLAPIENTRY
_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
                                  GLsizei bufSize, GLsizei *length,
                                  GLsizei *size, GLenum *type, GLchar *name)
{
   const struct gl_shader_program *shProg;
   struct gl_program_resource *res;
   GET_CURRENT_CONTEXT(ctx);

   shProg = _mesa_lookup_shader_program(ctx, program);
   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glGetTransformFeedbackVarying(program=%u)", program);
      return;
   }

   res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg,
                                           GL_TRANSFORM_FEEDBACK_VARYING,
                                           index);
   if (!res) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glGetTransformFeedbackVarying(index=%u)", index);
      return;
   }

   /* return the varying's name and length */
   _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));

   /* return the datatype and value's size (in datatype units) */
   if (type)
      _mesa_program_resource_prop((struct gl_shader_program *) shProg,
                                  res, index, GL_TYPE, (GLint*) type,
                                  "glGetTransformFeedbackVarying");
   if (size)
      _mesa_program_resource_prop((struct gl_shader_program *) shProg,
                                  res, index, GL_ARRAY_SIZE, (GLint*) size,
                                  "glGetTransformFeedbackVarying");
}
Esempio n. 21
0
/**
 * Called via ctx->Driver.GetUniformLocation().
 */
GLint
_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);
   if (shProg) {
      GLuint loc;
      for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
         const struct gl_program_parameter *u
            = shProg->Uniforms->Parameters + loc;
         /* XXX this is a temporary simplification / short-cut.
          * We need to handle things like "e.c[0].b" as seen in the
          * GLSL orange book, page 189.
          */
         if ((u->Type == PROGRAM_UNIFORM ||
              u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
            return loc;
         }
      }
   }
   return -1;

}
Esempio n. 22
0
/**
 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
 * DeleteProgramARB.
 */
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(ctx, name);
   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
      return;
   }

   shProg->DeletePending = GL_TRUE;

   /* effectively, decr shProg's refcount */
   _mesa_reference_shader_program(ctx, &shProg, NULL);
}
Esempio n. 23
0
/**
 * This function specifies the transform feedback outputs to be written
 * to the feedback buffer(s), and in what order.
 */
void GLAPIENTRY
_mesa_TransformFeedbackVaryings(GLuint program, GLsizei count,
                                const GLchar * const *varyings,
                                GLenum bufferMode)
{
   struct gl_shader_program *shProg;
   GLint i;
   GET_CURRENT_CONTEXT(ctx);

   /* From the ARB_transform_feedback2 specification:
    * "The error INVALID_OPERATION is generated by TransformFeedbackVaryings
    *  if the current transform feedback object is active, even if paused."
    */
   if (ctx->TransformFeedback.CurrentObject->Active) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
               "glTransformFeedbackVaryings(current object is active)");
      return;
   }

   switch (bufferMode) {
   case GL_INTERLEAVED_ATTRIBS:
      break;
   case GL_SEPARATE_ATTRIBS:
      break;
   default:
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glTransformFeedbackVaryings(bufferMode)");
      return;
   }

   if (count < 0 ||
       (bufferMode == GL_SEPARATE_ATTRIBS &&
        (GLuint) count > ctx->Const.MaxTransformFeedbackBuffers)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glTransformFeedbackVaryings(count=%d)", count);
      return;
   }

   shProg = _mesa_lookup_shader_program(ctx, program);
   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glTransformFeedbackVaryings(program=%u)", program);
      return;
   }

   if (ctx->Extensions.ARB_transform_feedback3) {
      if (bufferMode == GL_INTERLEAVED_ATTRIBS) {
         unsigned buffers = 1;

         for (i = 0; i < count; i++) {
            if (strcmp(varyings[i], "gl_NextBuffer") == 0)
               buffers++;
         }

         if (buffers > ctx->Const.MaxTransformFeedbackBuffers) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glTransformFeedbackVaryings(too many gl_NextBuffer "
                        "occurences)");
            return;
         }
      } else {
         for (i = 0; i < count; i++) {
            if (strcmp(varyings[i], "gl_NextBuffer") == 0 ||
                strcmp(varyings[i], "gl_SkipComponents1") == 0 ||
                strcmp(varyings[i], "gl_SkipComponents2") == 0 ||
                strcmp(varyings[i], "gl_SkipComponents3") == 0 ||
                strcmp(varyings[i], "gl_SkipComponents4") == 0) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glTransformFeedbackVaryings(SEPARATE_ATTRIBS,"
                           "varying=%s)",
                           varyings[i]);
               return;
            }
         }
      }
   }

   /* free existing varyings, if any */
   for (i = 0; i < (GLint) shProg->TransformFeedback.NumVarying; i++) {
      free(shProg->TransformFeedback.VaryingNames[i]);
   }
   free(shProg->TransformFeedback.VaryingNames);

   /* allocate new memory for varying names */
   shProg->TransformFeedback.VaryingNames =
      malloc(count * sizeof(GLchar *));

   if (!shProg->TransformFeedback.VaryingNames) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()");
      return;
   }

   /* Save the new names and the count */
   for (i = 0; i < count; i++) {
      shProg->TransformFeedback.VaryingNames[i] = strdup(varyings[i]);
   }
   shProg->TransformFeedback.NumVarying = count;

   shProg->TransformFeedback.BufferMode = bufferMode;

   /* No need to invoke FLUSH_VERTICES or flag NewTransformFeedback since
    * the varyings won't be used until shader link time.
    */
}
Esempio n. 24
0
static GLboolean brwProgramStringNotify( struct gl_context *ctx,
                                         GLenum target,
                                         struct gl_program *prog )
{
   struct brw_context *brw = brw_context(ctx);
   int i;

   if (target == GL_FRAGMENT_PROGRAM_ARB) {
      struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
      struct brw_fragment_program *newFP = brw_fragment_program(fprog);
      const struct brw_fragment_program *curFP =
         brw_fragment_program_const(brw->fragment_program);
      struct gl_shader_program *shader_program;

      if (newFP == curFP)
	 brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM;
      newFP->id = brw->program_id++;      

      /* Don't reject fragment shaders for their Mesa IR state when we're
       * using the new FS backend.
       */
      shader_program = _mesa_lookup_shader_program(ctx, prog->Id);
      if (shader_program
	  && shader_program->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
	 return GL_TRUE;
      }
   }
   else if (target == GL_VERTEX_PROGRAM_ARB) {
      struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
      struct brw_vertex_program *newVP = brw_vertex_program(vprog);
      const struct brw_vertex_program *curVP =
         brw_vertex_program_const(brw->vertex_program);

      if (newVP == curVP)
	 brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM;
      if (newVP->program.IsPositionInvariant) {
	 _mesa_insert_mvp_code(ctx, &newVP->program);
      }
      newVP->id = brw->program_id++;      

      /* Also tell tnl about it:
       */
      _tnl_program_string(ctx, target, prog);
   }

   /* Reject programs with subroutines, which are totally broken at the moment
    * (all program flows return when any program flow returns, and
    * the VS also hangs if a function call calls a function.
    *
    * See piglit glsl-{vs,fs}-functions-[23] tests.
    */
   for (i = 0; i < prog->NumInstructions; i++) {
      struct prog_instruction *inst = prog->Instructions + i;
      int r;

      if (prog->Instructions[i].Opcode == OPCODE_CAL) {
	 shader_error(ctx, prog,
		      "i965 driver doesn't yet support uninlined function "
		      "calls.  Move to using a single return statement at "
		      "the end of the function to work around it.\n");
	 return GL_FALSE;
      }

      if (prog->Instructions[i].Opcode == OPCODE_RET) {
	 shader_error(ctx, prog,
		      "i965 driver doesn't yet support \"return\" "
		      "from main().\n");
	 return GL_FALSE;
      }

      for (r = 0; r < _mesa_num_inst_src_regs(inst->Opcode); r++) {
	 if (prog->Instructions[i].SrcReg[r].RelAddr &&
	     prog->Instructions[i].SrcReg[r].File == PROGRAM_INPUT) {
	    shader_error(ctx, prog,
			 "Variable indexing of shader inputs unsupported\n");
	    return GL_FALSE;
	 }
      }

      if (target == GL_FRAGMENT_PROGRAM_ARB &&
	  prog->Instructions[i].DstReg.RelAddr &&
	  prog->Instructions[i].DstReg.File == PROGRAM_OUTPUT) {
	 shader_error(ctx, prog,
		      "Variable indexing of FS outputs unsupported\n");
	 return GL_FALSE;
      }
      if (target == GL_FRAGMENT_PROGRAM_ARB) {
	 if ((prog->Instructions[i].DstReg.RelAddr &&
	      prog->Instructions[i].DstReg.File == PROGRAM_TEMPORARY) ||
	     (prog->Instructions[i].SrcReg[0].RelAddr &&
	      prog->Instructions[i].SrcReg[0].File == PROGRAM_TEMPORARY) ||
	     (prog->Instructions[i].SrcReg[1].RelAddr &&
	      prog->Instructions[i].SrcReg[1].File == PROGRAM_TEMPORARY) ||
	     (prog->Instructions[i].SrcReg[2].RelAddr &&
	      prog->Instructions[i].SrcReg[2].File == PROGRAM_TEMPORARY)) {
	    shader_error(ctx, prog,
			 "Variable indexing of variable arrays in the FS "
			 "unsupported\n");
	    return GL_FALSE;
	 }
      }
   }

   return GL_TRUE;
}
Esempio n. 25
0
/**
 * glGetProgramiv() - get shader program state.
 * Note that this is for GLSL shader programs, not ARB vertex/fragment
 * programs (see glGetProgramivARB).
 */
static void
get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *params)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
      return;
   }

   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 = _mesa_count_active_attribs(shProg);
      break;
   case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
      *params = _mesa_longest_attribute_name_length(shProg);
      break;
   case GL_ACTIVE_UNIFORMS:
      *params = shProg->NumUserUniformStorage;
      break;
   case GL_ACTIVE_UNIFORM_MAX_LENGTH: {
      unsigned i;
      GLint max_len = 0;

      for (i = 0; i < shProg->NumUserUniformStorage; i++) {
	 /* Add one for the terminating NUL character.
	  */
	 const GLint len = strlen(shProg->UniformStorage[i].name) + 1;

	 if (len > max_len)
	    max_len = len;
      }

      *params = max_len;
      break;
   }
   case GL_PROGRAM_BINARY_LENGTH_OES:
      *params = 0;
      break;
#if FEATURE_EXT_transform_feedback
   case GL_TRANSFORM_FEEDBACK_VARYINGS:
      *params = shProg->TransformFeedback.NumVarying;
      break;
   case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
      *params = longest_feedback_varying_name(shProg) + 1;
      break;
   case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
      *params = shProg->TransformFeedback.BufferMode;
      break;
#endif
#if FEATURE_ARB_geometry_shader4
   case GL_GEOMETRY_VERTICES_OUT_ARB:
      *params = shProg->Geom.VerticesOut;
      break;
   case GL_GEOMETRY_INPUT_TYPE_ARB:
      *params = shProg->Geom.InputType;
      break;
   case GL_GEOMETRY_OUTPUT_TYPE_ARB:
      *params = shProg->Geom.OutputType;
      break;
#endif
   default:
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
      return;
   }
}
Esempio n. 26
0
static GLboolean
is_program(struct gl_context *ctx, GLuint name)
{
   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
   return shProg ? GL_TRUE : GL_FALSE;
}
Esempio n. 27
0
/**
 * glGetProgramiv() - get shader program state.
 * Note that this is for GLSL shader programs, not ARB vertex/fragment
 * programs (see glGetProgramivARB).
 */
static void
get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *params)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);

   /* Is transform feedback available in this context?
    */
   const bool has_xfb =
      (ctx->API == API_OPENGL && ctx->Extensions.EXT_transform_feedback)
      || ctx->API == API_OPENGL_CORE
      || _mesa_is_gles3(ctx);

   /* Are geometry shaders available in this context?
    */
   const bool has_gs =
      _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4;

   /* Are uniform buffer objects available in this context?
    */
   const bool has_ubo =
      (ctx->API == API_OPENGL && ctx->Extensions.ARB_uniform_buffer_object)
      || ctx->API == API_OPENGL_CORE
      || _mesa_is_gles3(ctx);

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
      return;
   }

   switch (pname) {
   case GL_DELETE_STATUS:
      *params = shProg->DeletePending;
      return;
   case GL_LINK_STATUS:
      *params = shProg->LinkStatus;
      return;
   case GL_VALIDATE_STATUS:
      *params = shProg->Validated;
      return;
   case GL_INFO_LOG_LENGTH:
      *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
      return;
   case GL_ATTACHED_SHADERS:
      *params = shProg->NumShaders;
      return;
   case GL_ACTIVE_ATTRIBUTES:
      *params = _mesa_count_active_attribs(shProg);
      return;
   case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
      *params = _mesa_longest_attribute_name_length(shProg);
      return;
   case GL_ACTIVE_UNIFORMS:
      *params = shProg->NumUserUniformStorage;
      return;
   case GL_ACTIVE_UNIFORM_MAX_LENGTH: {
      unsigned i;
      GLint max_len = 0;

      for (i = 0; i < shProg->NumUserUniformStorage; i++) {
	 /* Add one for the terminating NUL character.
	  */
	 const GLint len = strlen(shProg->UniformStorage[i].name) + 1;

	 if (len > max_len)
	    max_len = len;
      }

      *params = max_len;
      return;
   }
   case GL_TRANSFORM_FEEDBACK_VARYINGS:
      if (!has_xfb)
         break;
      *params = shProg->TransformFeedback.NumVarying;
      return;
   case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
      if (!has_xfb)
         break;
      *params = longest_feedback_varying_name(shProg) + 1;
      return;
   case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
      if (!has_xfb)
         break;
      *params = shProg->TransformFeedback.BufferMode;
      return;
   case GL_GEOMETRY_VERTICES_OUT_ARB:
      if (!has_gs)
         break;
      *params = shProg->Geom.VerticesOut;
      return;
   case GL_GEOMETRY_INPUT_TYPE_ARB:
      if (!has_gs)
         break;
      *params = shProg->Geom.InputType;
      return;
   case GL_GEOMETRY_OUTPUT_TYPE_ARB:
      if (!has_gs)
         break;
      *params = shProg->Geom.OutputType;
      return;
   case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: {
      unsigned i;
      GLint max_len = 0;

      if (!has_ubo)
         break;

      for (i = 0; i < shProg->NumUniformBlocks; i++) {
	 /* Add one for the terminating NUL character.
	  */
	 const GLint len = strlen(shProg->UniformBlocks[i].Name) + 1;

	 if (len > max_len)
	    max_len = len;
      }

      *params = max_len;
      return;
   }
   case GL_ACTIVE_UNIFORM_BLOCKS:
      if (!has_ubo)
         break;

      *params = shProg->NumUniformBlocks;
      return;
   default:
      break;
   }

   _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname=%s)",
               _mesa_lookup_enum_by_nr(pname));
}
Esempio n. 28
0
/**
 * glGetProgramiv() - get shader program state.
 * Note that this is for GLSL shader programs, not ARB vertex/fragment
 * programs (see glGetProgramivARB).
 */
static void
get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *params)
{
   struct gl_shader_program *shProg
      = _mesa_lookup_shader_program(ctx, program);

   /* Is transform feedback available in this context?
    */
   const bool has_xfb =
      (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_transform_feedback)
      || ctx->API == API_OPENGL_CORE
      || _mesa_is_gles3(ctx);

   /* True if geometry shaders (of the form that was adopted into GLSL 1.50
    * and GL 3.2) are available in this context
    */
   const bool has_core_gs = _mesa_is_desktop_gl(ctx) && ctx->Version >= 32;

   /* Are uniform buffer objects available in this context?
    */
   const bool has_ubo =
      (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_uniform_buffer_object)
      || ctx->API == API_OPENGL_CORE
      || _mesa_is_gles3(ctx);

   if (!shProg) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
      return;
   }

   switch (pname) {
   case GL_DELETE_STATUS:
      *params = shProg->DeletePending;
      return;
   case GL_LINK_STATUS:
      *params = shProg->LinkStatus;
      return;
   case GL_VALIDATE_STATUS:
      *params = shProg->Validated;
      return;
   case GL_INFO_LOG_LENGTH:
      *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
      return;
   case GL_ATTACHED_SHADERS:
      *params = shProg->NumShaders;
      return;
   case GL_ACTIVE_ATTRIBUTES:
      *params = _mesa_count_active_attribs(shProg);
      return;
   case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
      *params = _mesa_longest_attribute_name_length(shProg);
      return;
   case GL_ACTIVE_UNIFORMS:
      *params = shProg->NumUserUniformStorage;
      return;
   case GL_ACTIVE_UNIFORM_MAX_LENGTH: {
      unsigned i;
      GLint max_len = 0;

      for (i = 0; i < shProg->NumUserUniformStorage; i++) {
	 /* Add one for the terminating NUL character for a non-array, and
	  * 4 for the "[0]" and the NUL for an array.
	  */
	 const GLint len = strlen(shProg->UniformStorage[i].name) + 1 +
	     ((shProg->UniformStorage[i].array_elements != 0) ? 3 : 0);

	 if (len > max_len)
	    max_len = len;
      }

      *params = max_len;
      return;
   }
   case GL_TRANSFORM_FEEDBACK_VARYINGS:
      if (!has_xfb)
         break;
      *params = shProg->TransformFeedback.NumVarying;
      return;
   case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: {
      unsigned i;
      GLint max_len = 0;
      if (!has_xfb)
         break;

      for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
         /* Add one for the terminating NUL character.
          */
         const GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]) + 1;

         if (len > max_len)
            max_len = len;
      }

      *params = max_len;
      return;
   }
   case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
      if (!has_xfb)
         break;
      *params = shProg->TransformFeedback.BufferMode;
      return;
   case GL_GEOMETRY_VERTICES_OUT:
      if (!has_core_gs)
         break;
      if (check_gs_query(ctx, shProg))
         *params = shProg->Geom.VerticesOut;
      return;
   case GL_GEOMETRY_INPUT_TYPE:
      if (!has_core_gs)
         break;
      if (check_gs_query(ctx, shProg))
         *params = shProg->Geom.InputType;
      return;
   case GL_GEOMETRY_OUTPUT_TYPE:
      if (!has_core_gs)
         break;
      if (check_gs_query(ctx, shProg))
         *params = shProg->Geom.OutputType;
      return;
   case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: {
      unsigned i;
      GLint max_len = 0;

      if (!has_ubo)
         break;

      for (i = 0; i < shProg->NumUniformBlocks; i++) {
	 /* Add one for the terminating NUL character.
	  */
	 const GLint len = strlen(shProg->UniformBlocks[i].Name) + 1;

	 if (len > max_len)
	    max_len = len;
      }

      *params = max_len;
      return;
   }
   case GL_ACTIVE_UNIFORM_BLOCKS:
      if (!has_ubo)
         break;

      *params = shProg->NumUniformBlocks;
      return;
   case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
      /* This enum isn't part of the OES extension for OpenGL ES 2.0.  It is
       * only available with desktop OpenGL 3.0+ with the
       * GL_ARB_get_program_binary extension or OpenGL ES 3.0.
       *
       * On desktop, we ignore the 3.0+ requirement because it is silly.
       */
      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
         break;

      *params = shProg->BinaryRetreivableHint;
      return;
   case GL_PROGRAM_BINARY_LENGTH:
      *params = 0;
      return;
   case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
      if (!ctx->Extensions.ARB_shader_atomic_counters)
         break;

      *params = shProg->NumAtomicBuffers;
      return;
   default:
      break;
   }

   _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname=%s)",
               _mesa_lookup_enum_by_nr(pname));
}