void GLAPIENTRY _mesa_GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar * const *uniformNames, GLuint *uniformIndices) { GET_CURRENT_CONTEXT(ctx); GLsizei i; struct gl_shader_program *shProg; if (!ctx->Extensions.ARB_uniform_buffer_object) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformIndices"); return; } shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetUniformIndices"); if (!shProg) return; if (uniformCount < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformIndices(uniformCount < 0)"); return; } for (i = 0; i < uniformCount; i++) { unsigned offset; uniformIndices[i] = _mesa_get_uniform_location(ctx, shProg, uniformNames[i], &offset); } }
GLuint GLAPIENTRY _mesa_GetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName) { GET_CURRENT_CONTEXT(ctx); GLuint i; struct gl_shader_program *shProg; if (!ctx->Extensions.ARB_uniform_buffer_object) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformBlockIndex"); return GL_INVALID_INDEX; } shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetUniformBlockIndex"); if (!shProg) return GL_INVALID_INDEX; for (i = 0; i < shProg->NumUniformBlocks; i++) { if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName)) return i; } return GL_INVALID_INDEX; }
/** * For GL_EXT_separate_shader_objects */ void GLAPIENTRY _mesa_UseShaderProgramEXT(GLenum type, GLuint program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = NULL; ASSERT_OUTSIDE_BEGIN_END(ctx); if (!validate_shader_target(ctx, type)) { _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)"); return; } if (ctx->TransformFeedback.CurrentObject->Active && !ctx->TransformFeedback.CurrentObject->Paused) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseShaderProgramEXT(transform feedback is active)"); return; } if (program) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseShaderProgramEXT"); if (shProg == NULL) return; if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseShaderProgramEXT(program not linked)"); return; } } _mesa_use_shader_program(ctx, type, shProg); }
void GLAPIENTRY _mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; if (!ctx->Extensions.ARB_uniform_buffer_object) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv"); return; } if (bufSize < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformName(bufSize %d < 0)", bufSize); return; } shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniformName"); if (!shProg) return; if (uniformIndex >= shProg->NumUserUniformStorage) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); return; } if (uniformName) { _mesa_get_uniform_name(& shProg->UniformStorage[uniformIndex], bufSize, length, uniformName); } }
void GLAPIENTRY _mesa_ProgramParameteriARB(GLuint program, GLenum pname, GLint value) { struct gl_shader_program *shProg; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramParameteri"); if (!shProg) return; switch (pname) { case GL_GEOMETRY_VERTICES_OUT_ARB: if (value < 1 || (unsigned) value > ctx->Const.MaxGeometryOutputVertices) { _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d", value); return; } shProg->Geom.VerticesOut = value; break; case GL_GEOMETRY_INPUT_TYPE_ARB: switch (value) { case GL_POINTS: case GL_LINES: case GL_LINES_ADJACENCY_ARB: case GL_TRIANGLES: case GL_TRIANGLES_ADJACENCY_ARB: shProg->Geom.InputType = value; break; default: _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameteri(geometry input type = %s", _mesa_lookup_enum_by_nr(value)); return; } break; case GL_GEOMETRY_OUTPUT_TYPE_ARB: switch (value) { case GL_POINTS: case GL_LINE_STRIP: case GL_TRIANGLE_STRIP: shProg->Geom.OutputType = value; break; default: _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameteri(geometry output type = %s", _mesa_lookup_enum_by_nr(value)); return; } break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteriARB(pname=%s)", _mesa_lookup_enum_by_nr(pname)); break; } }
extern "C" void GLAPIENTRY _mesa_GetActiveUniformARB(GLhandleARB program, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *nameOut) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); if (!shProg) return; if (index >= shProg->NumUserUniformStorage) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); return; } const struct gl_uniform_storage *const uni = &shProg->UniformStorage[index]; if (nameOut) { _mesa_copy_string(nameOut, maxLength, length, uni->name); } if (size) { /* array_elements is zero for non-arrays, but the API requires that 1 be * returned. */ *size = MAX2(1, uni->array_elements); } if (type) { *type = uni->type->gl_type; } }
/** * Use the named shader program for subsequent glUniform calls (if pipeline * bound) */ void GLAPIENTRY _mesa_ActiveShaderProgram(GLuint pipeline, GLuint program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = NULL; struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); if (program != 0) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glActiveShaderProgram(program)"); if (shProg == NULL) return; } if (!pipe) { _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)"); return; } /* Object is created by any Pipeline call but glGenProgramPipelines, * glIsProgramPipeline and GetProgramPipelineInfoLog */ pipe->EverBound = GL_TRUE; if ((shProg != NULL) && !shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(program %u not linked)", shProg->Name); return; } _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg); }
GLint GLAPIENTRY _mesa_GetFragDataIndex(GLuint program, const GLchar *name) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *const shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex"); if (!shProg) { return -1; } if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFragDataIndex(program not linked)"); return -1; } if (!name) return -1; if (strncmp(name, "gl_", 3) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFragDataIndex(illegal name)"); return -1; } /* Not having a fragment shader is not an error. */ if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) return -1; return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT, name); }
void GLAPIENTRY _mesa_GetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv"); if (!shProg || !params) return; /* The error INVALID_VALUE is generated if <propCount> is zero. * Note that we check < 0 here because it makes sense to bail early. */ if (propCount <= 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramResourceiv(propCount <= 0)"); return; } /* No need to write any properties, user requested none. */ if (bufSize == 0) return; _mesa_get_program_resourceiv(shProg, programInterface, index, propCount, props, bufSize, length, params); }
void GLAPIENTRY _mesa_GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) { GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) { _mesa_debug(ctx, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n", program, _mesa_enum_to_string(programInterface), index, bufSize, length, name); } struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceName"); if (!shProg || !name) return; if (programInterface == GL_ATOMIC_COUNTER_BUFFER || !supported_interface_enum(ctx, programInterface)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)", _mesa_enum_to_string(programInterface)); return; } _mesa_get_program_resource_name(shProg, programInterface, index, bufSize, length, name, "glGetProgramResourceName"); }
void GLAPIENTRY _mesa_GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceName"); /* Set user friendly return values in case of errors. */ if (name) *name = '\0'; if (length) *length = 0; if (!shProg || !name) return; if (programInterface == GL_ATOMIC_COUNTER_BUFFER || !supported_interface_enum(programInterface)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)", _mesa_lookup_enum_by_nr(programInterface)); return; } _mesa_get_program_resource_name(shProg, programInterface, index, bufSize, length, name, "glGetProgramResourceName"); }
/** * For GL_EXT_separate_shader_objects */ void GLAPIENTRY _mesa_UseShaderProgramEXT(GLenum type, GLuint program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = NULL; if (!validate_shader_target(ctx, type)) { _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)"); return; } if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseShaderProgramEXT(transform feedback is active)"); return; } if (program) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseShaderProgramEXT"); if (shProg == NULL) return; if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseShaderProgramEXT(program not linked)"); return; } } _mesa_use_shader_program(ctx, type, shProg); }
void GLAPIENTRY _mesa_GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary) { struct gl_shader_program *shProg; GET_CURRENT_CONTEXT(ctx); shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramBinary"); if (!shProg) return; if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramBinary(program %u not linked)", shProg->Name); return; } if (bufSize < 0){ _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramBinary(bufSize < 0)"); return; } /* The ARB_get_program_binary spec says: * * "If <length> is NULL, then no length is returned." */ if (length != NULL) *length = 0; (void) binaryFormat; (void) binary; }
void GLAPIENTRY _mesa_UseProgram(GLhandleARB program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram(transform feedback active)"); return; } if (program) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); if (!shProg) { return; } if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram(program %u not linked)", program); return; } /* debug code */ if (ctx->Shader.Flags & GLSL_USE_PROG) { print_shader_info(shProg); } } else { shProg = NULL; } _mesa_use_program(ctx, shProg); }
/** * Attach shader to a shader program. */ static void attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg; struct gl_shader *sh; GLuint i, n; const bool same_type_disallowed = _mesa_is_gles(ctx); 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) { /* The shader is already attched to this program. The * GL_ARB_shader_objects spec says: * * "The error INVALID_OPERATION is generated by AttachObjectARB * if <obj> is already attached to <containerObj>." */ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); return; } else if (same_type_disallowed && shProg->Shaders[i]->Type == sh->Type) { /* Shader with the same type is already attached to this program, * OpenGL ES 2.0 and 3.0 specs say: * * "Multiple shader objects of the same type may not be attached * to a single program object. [...] The error INVALID_OPERATION * is generated if [...] another shader object of the same type * as shader is already attached to program." */ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); 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++; }
void GLAPIENTRY _mesa_ProgramUniform1ui(GLuint program, GLint location, GLuint v0) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform1ui"); _mesa_uniform(ctx, shProg, location, 1, &v0, GL_UNSIGNED_INT); }
void GLAPIENTRY _mesa_ProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniformMatrix4x3fv"); _mesa_uniform_matrix(ctx, shProg, 4, 3, location, count, transpose, value); }
void GLAPIENTRY _mesa_ProgramUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint *value) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform4uiv"); _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT_VEC4); }
GLint GLAPIENTRY _mesa_GetFragDataLocation(GLuint program, const GLchar *name) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *const shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation"); if (!shProg) { return -1; } if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFragDataLocation(program not linked)"); return -1; } if (!name) return -1; if (strncmp(name, "gl_", 3) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFragDataLocation(illegal name)"); return -1; } /* Not having a fragment shader is not an error. */ if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) return -1; exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; foreach_list(node, ir) { const ir_variable *const var = ((ir_instruction *) node)->as_variable(); /* The extra check against FRAG_RESULT_DATA0 is because * glGetFragDataLocation cannot be used on "conventional" attributes. * * From page 95 of the OpenGL 3.0 spec: * * "If name is not an active attribute, if name is a conventional * attribute, or if an error occurs, -1 will be returned." */ if (var == NULL || var->mode != ir_var_out || var->location == -1 || var->location < FRAG_RESULT_DATA0) continue; if (strcmp(var->name, name) == 0) return var->location - FRAG_RESULT_DATA0; } return -1; }
void GLAPIENTRY _mesa_GetActiveAttribARB(GLhandleARB program, GLuint desired_index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); if (!shProg) return; if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(program not linked)"); return; } if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)"); return; } exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; unsigned current_index = 0; foreach_list(node, ir) { const ir_variable *const var = ((ir_instruction *) node)->as_variable(); if (var == NULL || var->mode != ir_var_in || var->location == -1) continue; if (current_index == desired_index) { _mesa_copy_string(name, maxLength, length, var->name); if (size) *size = (var->type->is_array()) ? var->type->length : 1; if (type) *type = var->type->gl_type; return; } current_index++; } /* If the loop did not return early, the caller must have asked for * an index that did not exit. Set an error. */ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); }
/** * For GL_EXT_separate_shader_objects */ void GLAPIENTRY _mesa_ActiveProgramEXT(GLuint program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg = (program != 0) ? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT") : NULL; _mesa_active_program(ctx, shProg, "glActiveProgramEXT"); return; }
void GLAPIENTRY _mesa_ProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1) { GET_CURRENT_CONTEXT(ctx); GLint v[2]; struct gl_shader_program *shProg; v[0] = v0; v[1] = v1; shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform2i"); _mesa_uniform(ctx, shProg, location, 1, v, GL_INT_VEC2); }
GLint GLAPIENTRY _mesa_GetFragDataLocation(GLuint program, const GLchar *name) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *const shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation"); if (!shProg) { return -1; } if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFragDataLocation(program not linked)"); return -1; } if (!name) return -1; if (strncmp(name, "gl_", 3) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFragDataLocation(illegal name)"); return -1; } /* Not having a fragment shader is not an error. */ if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) return -1; unsigned array_index = 0; struct gl_program_resource *res = _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name, &array_index); if (!res) return -1; GLint loc = program_resource_location(shProg, res, name, array_index); /* The extra check against against 0 is made because of builtin-attribute * locations that have offset applied. Function program_resource_location * can return built-in attribute locations < 0 and glGetFragDataLocation * cannot be used on "conventional" attributes. * * From page 95 of the OpenGL 3.0 spec: * * "If name is not an active attribute, if name is a conventional * attribute, or if an error occurs, -1 will be returned." */ return (loc >= 0) ? loc : -1; }
void GLAPIENTRY _mesa_GetActiveAttrib(GLuint program, GLuint desired_index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLchar * name) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; if (maxLength < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)"); return; } shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); if (!shProg) return; if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(program not linked)"); return; } if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)"); return; } struct gl_program_resource *res = _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT, desired_index); /* User asked for index that does not exist. */ if (!res) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); return; } const gl_shader_variable *const var = RESOURCE_VAR(res); const char *var_name = var->name; _mesa_copy_string(name, maxLength, length, var_name); if (size) _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE, size, "glGetActiveAttrib"); if (type) _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE, (GLint *) type, "glGetActiveAttrib"); }
void GLAPIENTRY _mesa_ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { GET_CURRENT_CONTEXT(ctx); GLfloat v[3]; struct gl_shader_program *shProg; v[0] = v0; v[1] = v1; v[2] = v2; shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform3f"); _mesa_uniform(ctx, shProg, location, 1, v, GL_FLOAT_VEC3); }
void GLAPIENTRY _mesa_UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; if (!ctx->Extensions.ARB_uniform_buffer_object) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformBlockBinding"); return; } shProg = _mesa_lookup_shader_program_err(ctx, program, "glUniformBlockBinding"); if (!shProg) return; if (uniformBlockIndex >= shProg->NumUniformBlocks) { _mesa_error(ctx, GL_INVALID_VALUE, "glUniformBlockBinding(block index %u >= %u)", uniformBlockIndex, shProg->NumUniformBlocks); return; } if (uniformBlockBinding >= ctx->Const.MaxUniformBufferBindings) { _mesa_error(ctx, GL_INVALID_VALUE, "glUniformBlockBinding(block binding %u >= %u)", uniformBlockBinding, ctx->Const.MaxUniformBufferBindings); return; } if (shProg->UniformBlocks[uniformBlockIndex].Binding != uniformBlockBinding) { int i; FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer; shProg->UniformBlocks[uniformBlockIndex].Binding = uniformBlockBinding; for (i = 0; i < MESA_SHADER_STAGES; i++) { int stage_index = shProg->UniformBlockStageIndex[i][uniformBlockIndex]; if (stage_index != -1) { struct gl_shader *sh = shProg->_LinkedShaders[i]; sh->UniformBlocks[stage_index].Binding = uniformBlockBinding; } } } }
extern "C" void GLAPIENTRY _mesa_GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; struct gl_program_resource *res; GLenum res_prop; if (uniformCount < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(uniformCount < 0)"); return; } shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); if (!shProg) return; res_prop = resource_prop_from_uniform_prop(pname); /* We need to first verify that each entry exists as active uniform. If * not, generate error and do not cause any other side effects. * * In the case of and error condition, Page 16 (section 2.3.1 Errors) * of the OpenGL 4.5 spec says: * * "If the generating command modifies values through a pointer argu- * ment, no change is made to these values." */ for (int i = 0; i < uniformCount; i++) { if (!_mesa_program_resource_find_index(shProg, GL_UNIFORM, uniformIndices[i])) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)"); return; } } for (int i = 0; i < uniformCount; i++) { res = _mesa_program_resource_find_index(shProg, GL_UNIFORM, uniformIndices[i]); if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i], res_prop, ¶ms[i], "glGetActiveUniformsiv")) break; } }
GLint GLAPIENTRY _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name) { struct gl_shader_program *shProg; GET_CURRENT_CONTEXT(ctx); shProg = _mesa_lookup_shader_program_err(ctx, programObj, "glGetUniformLocation"); if (!shProg) return -1; return _mesa_get_uniform_location(ctx, shProg, name); }
void GLAPIENTRY _mesa_ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { GET_CURRENT_CONTEXT(ctx); GLuint v[4]; struct gl_shader_program *shProg; v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform4ui"); _mesa_uniform(ctx, shProg, location, 1, v, GL_UNSIGNED_INT_VEC4); }
GLint GLAPIENTRY _mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *const 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; /* Not having a vertex shader is not an error. */ if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) return -1; exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; foreach_list(node, ir) { const ir_variable *const var = ((ir_instruction *) node)->as_variable(); /* The extra check against VERT_ATTRIB_GENERIC0 is because * glGetAttribLocation cannot be used on "conventional" attributes. * * From page 95 of the OpenGL 3.0 spec: * * "If name is not an active attribute, if name is a conventional * attribute, or if an error occurs, -1 will be returned." */ if (var == NULL || var->mode != ir_var_in || var->location == -1 || var->location < VERT_ATTRIB_GENERIC0) continue; if (strcmp(var->name, name) == 0) return var->location - VERT_ATTRIB_GENERIC0; } return -1; }