package com.peterhi.ui.gl;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import javax.media.opengl.GL;
import javax.media.opengl.GL3;
import javax.media.opengl.GLException;
public final class GLShaderProgram extends GLObject {
private List<GLShader> shaderList;
public GLShaderProgram(GL gl) {
super(gl);
if (!gl.hasGLSL()) {
throw new IllegalArgumentException();
}
setId((Integer )glInvoke("glCreateProgram"));
}
public GLShader[] getShaders() {
if (isDisposed()) {
throw new GLException();
}
List<GLShader> shaderList = getShaderList();
return shaderList.toArray(new GLShader[shaderList.size()]);
}
public void addShader(GLShader shader) {
if (shader == null) {
throw new NullPointerException();
}
if (shader.isDisposed()) {
throw new IllegalArgumentException();
}
if (isDisposed()) {
throw new GLException();
}
glInvoke("glAttachShader",
int.class, getId(),
int.class, shader.getId()
);
getShaderList().add(shader);
}
public void removeShader(GLShader shader) {
if (shader == null) {
throw new NullPointerException();
}
if (shader.isDisposed()) {
throw new IllegalArgumentException();
}
if (isDisposed()) {
throw new GLException();
}
getShaderList().remove(shader);
glInvoke("glDetachShader",
int.class, getId(),
int.class, shader.getId()
);
}
public void clearShaders() {
if (isDisposed()) {
throw new IllegalStateException();
}
GLShader[] shaders = getShaders();
for (GLShader shader : shaders) {
removeShader(shader);
}
}
public void link() {
if (isDisposed()) {
throw new GLException();
}
glInvoke("glLinkProgram", int.class, getId());
int[] status = new int[1];
glInvoke("glGetProgramiv",
int.class, getId(),
int.class, GL3.GL_LINK_STATUS,
int[].class, status,
int.class, 0
);
if (status[0] == GL.GL_TRUE) {
return;
}
int[] length = new int[1];
glInvoke("glGetProgramiv",
int.class, getId(),
int.class, GL3.GL_INFO_LOG_LENGTH,
int[].class, length,
int.class, 0
);
byte[] chars = new byte[length[0]];
glInvoke("glGetProgramInfoLog",
int.class, getId(),
int.class, length[0],
int[].class, length,
int.class, 0,
byte[].class, chars,
int.class, 0
);
String message = new String(chars, Charset.forName("utf-8"));
throw new GLException(message);
}
public void validate() {
if (isDisposed()) {
throw new GLException();
}
glInvoke("glValidateProgram", int.class, getId());
int[] status = new int[1];
glInvoke("glGetProgramiv",
int.class, getId(),
int.class, GL3.GL_VALIDATE_STATUS,
int[].class, status,
int.class, 0
);
if (status[0] == GL.GL_TRUE) {
return;
}
int[] length = new int[1];
glInvoke("glGetProgramiv",
int.class, getId(),
int.class, GL3.GL_INFO_LOG_LENGTH,
int[].class, length,
int.class, 0
);
byte[] chars = new byte[length[0]];
glInvoke("glGetProgramInfoLog",
int.class, getId(),
int.class, length[0],
int[].class, length,
int.class, 0,
byte[].class, chars,
int.class, 0
);
String message = new String(chars, Charset.forName("utf-8"));
throw new GLException(message);
}
@Override
public void dispose() {
if (isDisposed()) {
return;
}
clearShaders();
glInvoke("glDeleteProgram", int.class, getId());
super.dispose();
}
public int getUniformLocation(String name) {
if (name == null) {
throw new NullPointerException();
}
if (name.isEmpty()) {
throw new IllegalArgumentException();
}
return (Integer )glInvoke("glGetUniformLocation",
int.class, getId(),
String.class, name
);
}
public void bind() {
if (isDisposed()) {
throw new GLException();
}
glInvoke("glUseProgram",
int.class, getId()
);
}
public void unbind() {
if (isDisposed()) {
throw new GLException();
}
glInvoke("glUseProgram",
int.class, 0
);
}
protected final List<GLShader> getShaderList() {
if (shaderList == null) {
shaderList = new ArrayList<GLShader>();
}
return shaderList;
}
}