jes-ruby/src/GLShader.cc

122 lines
2.9 KiB
C++

#include "GLShader.h"
typedef struct
{
GLuint id;
} GLShader;
static VALUE ruby_class;
static const char * get_shader_type_name(GLenum shader_type)
{
switch (shader_type)
{
case GL_VERTEX_SHADER:
return "vertex";
case GL_FRAGMENT_SHADER:
return "fragment";
default:
return "unknown";
}
}
static GLuint create_shader(GLenum shader_type, const char *source, size_t size)
{
GLuint id = glCreateShader(shader_type);
if (id > 0)
{
GLint status;
GLint length = size;
glShaderSource(id, 1, &source, &length);
glCompileShader(id);
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
GLint log_length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
char log[log_length + 1];
glGetShaderInfoLog(id, log_length, &log_length, log);
log[log_length] = '\0';
glDeleteShader(id);
rb_raise(rb_eRuntimeError,
"Error compiling %s shader:\n%s\n%s\n%s\n",
get_shader_type_name(shader_type),
"--------------------",
log,
"--------------------");
}
else
{
glDeleteShader(id);
rb_raise(rb_eRuntimeError,
"Error compiling %s shader",
get_shader_type_name(shader_type));
}
}
}
return id;
}
static void GLShader_free(void * ptr)
{
GLShader * glshader = (GLShader *)ptr;
if (glshader->id > 0)
{
glDeleteShader(glshader->id);
}
delete glshader;
}
static VALUE GLShader_new(VALUE klass, VALUE type, VALUE source)
{
GLenum shader_type;
if (type == ID2SYM(rb_intern("vertex")))
{
shader_type = GL_VERTEX_SHADER;
}
else if (type == ID2SYM(rb_intern("fragment")))
{
shader_type = GL_FRAGMENT_SHADER;
}
else
{
type = rb_funcall(type, rb_intern("inspect"), 0);
const char * type_cstr = StringValueCStr(type);
rb_raise(rb_eRuntimeError,
"Unknown shader type: %s",
type_cstr);
}
GLuint id = create_shader(shader_type,
RSTRING_PTR(source),
RSTRING_LEN(source));
GLShader * glshader = new GLShader();
glshader->id = id;
return Data_Wrap_Struct(klass, NULL, GLShader_free, glshader);
}
void GLShader_Init()
{
ruby_class = rb_define_class("GLShader", rb_cObject);
rb_define_singleton_method(ruby_class, "new", (VALUE(*)(...))GLShader_new, 2);
}
GLuint GLShader_id(VALUE shader)
{
GLShader * glshader;
Data_Get_Struct(shader, GLShader, glshader);
return glshader->id;
}