| // Copyright 2012 The go-gl Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package gl |
| |
| // #include "gl.h" |
| // GLuint workaroundGlGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) { |
| // return glGetUniformBlockIndex(program, uniformBlockName); |
| // } |
| import "C" |
| import "unsafe" |
| |
| // Program |
| |
| type Program Object |
| |
| func CreateProgram() Program { return Program(C.glCreateProgram()) } |
| |
| func (program Program) Delete() { C.glDeleteProgram(C.GLuint(program)) } |
| |
| func (program Program) AttachShader(shader Shader) { |
| C.glAttachShader(C.GLuint(program), C.GLuint(shader)) |
| } |
| |
| func (program Program) GetAttachedShaders() []Object { |
| var len C.GLint |
| C.glGetProgramiv(C.GLuint(program), C.GLenum(ACTIVE_UNIFORM_MAX_LENGTH), &len) |
| |
| objects := make([]Object, len) |
| C.glGetAttachedShaders(C.GLuint(program), C.GLsizei(len), nil, *((**C.GLuint)(unsafe.Pointer(&objects)))) |
| return objects |
| } |
| |
| func (program Program) DetachShader(shader Shader) { |
| C.glDetachShader(C.GLuint(program), C.GLuint(shader)) |
| } |
| |
| func (program Program) TransformFeedbackVaryings(names []string, buffer_mode GLenum) { |
| if len(names) == 0 { |
| C.glTransformFeedbackVaryings(C.GLuint(program), 0, (**C.GLchar)(nil), C.GLenum(buffer_mode)) |
| } else { |
| gl_names := make([]*C.GLchar, len(names)) |
| |
| for i := range names { |
| gl_names[i] = glString(names[i]) |
| } |
| |
| C.glTransformFeedbackVaryings(C.GLuint(program), C.GLsizei(len(gl_names)), &gl_names[0], C.GLenum(buffer_mode)) |
| |
| for _, s := range gl_names { |
| freeString(s) |
| } |
| } |
| } |
| |
| func (program Program) Link() { C.glLinkProgram(C.GLuint(program)) } |
| |
| func (program Program) Validate() { C.glValidateProgram(C.GLuint(program)) } |
| |
| func (program Program) Use() { C.glUseProgram(C.GLuint(program)) } |
| |
| func (program Program) Unuse() { C.glUseProgram(C.GLuint(0)) } |
| |
| // Deprecated, please use program.Unuse() |
| func ProgramUnuse() { C.glUseProgram(C.GLuint(0)) } |
| |
| func (program Program) GetInfoLog() string { |
| var length C.GLint |
| C.glGetProgramiv(C.GLuint(program), C.GLenum(INFO_LOG_LENGTH), &length) |
| // length is buffer size including null character |
| |
| if length > 1 { |
| log := C.malloc(C.size_t(length)) |
| defer C.free(log) |
| C.glGetProgramInfoLog(C.GLuint(program), C.GLsizei(length), nil, (*C.GLchar)(log)) |
| return C.GoString((*C.char)(log)) |
| } |
| return "" |
| |
| } |
| |
| func (program Program) Get(param GLenum) int { |
| var rv C.GLint |
| |
| C.glGetProgramiv(C.GLuint(program), C.GLenum(param), &rv) |
| return int(rv) |
| } |
| |
| // glGetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) |
| func (program Program) GetActiveUniform(index int) ( |
| Size int, Type GLenum, Name string) { |
| // Maximum length of active uniform name in program |
| bufSize := program.Get(ACTIVE_UNIFORM_MAX_LENGTH) |
| nameBuf := C.malloc(C.size_t(bufSize)) |
| defer C.free(nameBuf) |
| var size C.GLint |
| C.glGetActiveUniform( |
| C.GLuint(program), |
| C.GLuint(index), |
| C.GLsizei(bufSize), |
| nil, // length == len(Name) |
| &size, |
| (*C.GLenum)(&Type), |
| (*C.GLchar)(nameBuf)) |
| Name = C.GoString((*C.char)(nameBuf)) |
| Size = int(size) |
| return |
| } |
| |
| func (program Program) GetUniformiv(location UniformLocation, values []int32) { |
| if len(values) == 0 { |
| panic("Invalid values length") |
| } |
| // FIXME(jimt): This should really yield only one return value instead of using a slice. |
| // http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml |
| C.glGetUniformiv(C.GLuint(program), C.GLint(location), (*C.GLint)(&(values[0]))) |
| } |
| |
| func (program Program) GetUniformfv(location UniformLocation, values []float32) { |
| if len(values) == 0 { |
| panic("Invalid values length") |
| } |
| // FIXME(jimt): This should really yield only one return value instead of using a slice. |
| // http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml |
| C.glGetUniformfv(C.GLuint(program), C.GLint(location), (*C.GLfloat)(&(values[0]))) |
| } |
| |
| func (program Program) GetUniformLocation(name string) UniformLocation { |
| |
| cname := glString(name) |
| defer freeString(cname) |
| |
| return UniformLocation(C.glGetUniformLocation(C.GLuint(program), cname)) |
| } |
| |
| func (program Program) GetUniformBlockIndex(name string) UniformBlockIndex { |
| |
| cname := glString(name) |
| defer freeString(cname) |
| |
| // Workaround bug in GLEW < 1.8 where glGetUniformBlockIndex expects |
| // a string of char instead of a string of GLchar. We could ask everybody |
| // to bump their version of GLEW, or we could add a bit of C code that |
| // will silently cast GLchar into char. |
| |
| //return UniformBlockIndex(C.glGetUniformBlockIndex(C.GLuint(program), cname)) |
| return UniformBlockIndex(C.workaroundGlGetUniformBlockIndex(C.GLuint(program), cname)) |
| } |
| |
| func (program Program) UniformBlockBinding(index UniformBlockIndex, binding uint) { |
| C.glUniformBlockBinding(C.GLuint(program), C.GLuint(index), C.GLuint(binding)) |
| } |
| |
| // glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) |
| func (program Program) GetActiveAttrib(index int) ( |
| Size int, Type GLenum, Name string) { |
| // Maximum length of active uniform name in program |
| bufSize := program.Get(ACTIVE_ATTRIBUTE_MAX_LENGTH) |
| nameBuf := C.malloc(C.size_t(bufSize)) |
| defer C.free(nameBuf) |
| var size C.GLint |
| C.glGetActiveAttrib( |
| C.GLuint(program), |
| C.GLuint(index), |
| C.GLsizei(bufSize), |
| nil, // length == len(Name) |
| &size, |
| (*C.GLenum)(&Type), |
| (*C.GLchar)(nameBuf)) |
| Name = C.GoString((*C.char)(nameBuf)) |
| Size = int(size) |
| return |
| } |
| |
| func (program Program) GetAttribLocation(name string) AttribLocation { |
| |
| cname := glString(name) |
| defer freeString(cname) |
| |
| return AttribLocation(C.glGetAttribLocation(C.GLuint(program), cname)) |
| } |
| |
| func (program Program) BindAttribLocation(index AttribLocation, name string) { |
| |
| cname := glString(name) |
| defer freeString(cname) |
| |
| C.glBindAttribLocation(C.GLuint(program), C.GLuint(index), cname) |
| |
| } |
| |
| func (program Program) BindFragDataLocation(colorNumber int, name string) { |
| |
| cname := glString(name) |
| defer freeString(cname) |
| |
| C.glBindFragDataLocation(C.GLuint(program), C.GLuint(colorNumber), cname) |
| } |
| |
| func (program Program) GetFragDataLocation(name string) int { |
| |
| cname := glString(name) |
| defer freeString(cname) |
| |
| return int(C.glGetFragDataLocation(C.GLuint(program), cname)) |
| } |