+#include <GL/glew.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "opengl/shader-gl.h"
+
+ShaderGL::ShaderGL()
+{
+ sdr = 0;
+}
+
+ShaderGL::~ShaderGL()
+{
+ destroy();
+}
+
+bool ShaderGL::create(char *buf, unsigned int bsz, const char *fname)
+{
+ /* find shader type and create shader */
+ unsigned int stype;
+ switch(type) {
+ case SDR_VERTEX:
+ stype = GL_VERTEX_SHADER;
+ break;
+ case SDR_FRAGMENT:
+ stype = GL_FRAGMENT_SHADER;
+ break;
+ default:
+ fprintf(stderr, "Unknown shader type.\n");
+ return false;
+ }
+ sdr = glCreateShader(stype);
+
+ /* compile */
+ glShaderSource(sdr, 1, (const char **)&buf, 0);
+ glCompileShader(sdr);
+
+ delete [] buf;
+
+ /* check compile status */
+ int status;
+ glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
+ if(status)
+ printf("Successfully compiled shader: %s\n", fname);
+ else
+ fprintf(stderr, "Failed to compile %s shader.\n", fname);
+
+ /* print the info log */
+ int loglen;
+ glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
+ if(loglen > 0 && (buf = new char[loglen + 1])) {
+ glGetShaderInfoLog(sdr, loglen, 0, buf);
+ buf[loglen] = 0;
+ printf("%s\n", buf);
+
+ delete [] buf;
+ }
+
+ if(!status) {
+ destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void ShaderGL::destroy()
+{
+ if(sdr) {
+ glDeleteShader(sdr);
+ }
+ sdr = 0;
+ type = SDR_UNKNOWN;
+}
+
+void ShaderGL::attach(unsigned int prog)
+{
+ glAttachShader(prog, sdr);
+}
+
+/* Shader Program */
+
+ShaderProgramGL::ShaderProgramGL()
+{
+ prog = 0;
+ memset(shaders, 0, sizeof shaders / sizeof *shaders);
+}
+
+ShaderProgramGL::~ShaderProgramGL()
+{
+ destroy();
+}
+
+void ShaderProgramGL::destroy()
+{
+ glDeleteProgram(prog);
+ prog = 0;
+
+ delete_shaders();
+}
+
+void ShaderProgramGL::delete_shaders()
+{
+ for(unsigned int i=0; i<(sizeof shaders) / (sizeof *shaders); ++i) {
+ delete shaders[i];
+ }
+}
+
+bool ShaderProgramGL::link()
+{
+ glLinkProgram(prog);
+
+ int status;
+ glGetProgramiv(prog, GL_LINK_STATUS, &status);
+ if(status)
+ printf("Successfully linked shader program.\n");
+ else
+ printf("Failed to link shader program.\n");
+
+ int loglen;
+ glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &loglen);
+
+ char *buf;
+ if(loglen > 0 && (buf = new char[loglen + 1])) {
+ glGetProgramInfoLog(prog, loglen, 0, buf);
+ buf[loglen] = 0;
+ printf("%s\n", buf);
+ delete [] buf;
+ }
+
+ return status ? true : false;
+}
+
+bool ShaderProgramGL::load(const char *vfname, const char *ffname)
+{
+ Shader *vsdr = new ShaderGL;
+ if(!vsdr->load(vfname, SDR_VERTEX)) {
+ delete vsdr;
+ return false;
+ }
+
+ Shader *fsdr = new ShaderGL;
+ if(!fsdr->load(ffname, SDR_FRAGMENT)) {
+ delete vsdr;
+ delete fsdr;
+ return false;
+ }
+
+ prog = glCreateProgram();
+
+ vsdr->attach(prog);
+ fsdr->attach(prog);
+
+ if(!link()) {
+ delete vsdr;
+ delete fsdr;
+ glDeleteProgram(prog);
+ return false;
+ }
+
+ /* the order of shaders in the array is the order they have in
+ enum Type, so atm it goes like: VS, FS, ... because we have SDR_VERTEX,
+ SDR_FRAGMENT, ... */
+
+ shaders[0] = vsdr;
+ shaders[1] = fsdr;
+
+ return true;
+}
\ No newline at end of file