Shimatta Opengl: Shader Program: Implement compilation and use functions. Compilation from file still missing
This commit is contained in:
		@@ -51,7 +51,7 @@ ShimattaOpenglProgram *shimatta_opengl_program_new_from_file(const char *vertex_
 | 
			
		||||
 * @param program Shader Program
 | 
			
		||||
 * @param error_text Error message from compilation. May be NULL.
 | 
			
		||||
 * @param error_text_size Size in bytes of the error_text buffer. May be 0.
 | 
			
		||||
 * @return 0 if successful. If Error error text will hold the error
 | 
			
		||||
 * @return 0 if successful. If Error error text will hold the error. 1 is returned if program is already compiled
 | 
			
		||||
 */
 | 
			
		||||
int shimatta_opengl_program_compile(ShimattaOpenglProgram *program, char *error_text, size_t error_text_size);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ struct _ShimattaOpenglProgram {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	GLint shader_id;
 | 
			
		||||
	GLuint shader_id;
 | 
			
		||||
	gboolean compiled;
 | 
			
		||||
	char *fragment_file;
 | 
			
		||||
	char *vertex_file;
 | 
			
		||||
@@ -35,9 +35,42 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE(ShimattaOpenglProgram, shimatta_opengl_program, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static void shimatta_opengl_program_dispose(GObject *self)
 | 
			
		||||
{
 | 
			
		||||
	ShimattaOpenglProgram *prog;
 | 
			
		||||
	ShimattaOpenglProgramPrivate *priv;
 | 
			
		||||
 | 
			
		||||
	g_return_if_fail(SHIMATTA_IS_OPENGL_PROGRAM(self));
 | 
			
		||||
 | 
			
		||||
	prog = SHIMATTA_OPENGL_PROGRAM(self);
 | 
			
		||||
	priv = shimatta_opengl_program_get_instance_private(prog);
 | 
			
		||||
	if (priv->compiled) {
 | 
			
		||||
		priv->compiled = false;
 | 
			
		||||
		glDeleteProgram(priv->shader_id);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (priv->fragment_src)
 | 
			
		||||
		g_free(priv->fragment_src);
 | 
			
		||||
	if (priv->geometry_src)
 | 
			
		||||
		g_free(priv->geometry_src);
 | 
			
		||||
	if (priv->vertex_src)
 | 
			
		||||
		g_free(priv->vertex_src);
 | 
			
		||||
	if (priv->vertex_file)
 | 
			
		||||
		g_free(priv->vertex_file);
 | 
			
		||||
	if (priv->fragment_file)
 | 
			
		||||
		g_free(priv->fragment_file);
 | 
			
		||||
	if (priv->geometry_file)
 | 
			
		||||
		g_free(priv->geometry_file);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void shimatta_opengl_program_class_init(ShimattaOpenglProgramClass *klass)
 | 
			
		||||
{
 | 
			
		||||
	(void)klass;
 | 
			
		||||
	GObjectClass *oclass;
 | 
			
		||||
 | 
			
		||||
	oclass = G_OBJECT_CLASS(klass);
 | 
			
		||||
	oclass->dispose = shimatta_opengl_program_dispose;
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
@@ -73,3 +106,206 @@ ShimattaOpenglProgram *shimatta_opengl_program_new_from_data(const char *vertex_
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShimattaOpenglProgram *shimatta_opengl_program_new_from_file(const char *vertex_shader, const char *geometry_shader,
 | 
			
		||||
							     const char *fragment_shader)
 | 
			
		||||
{
 | 
			
		||||
	ShimattaOpenglProgram *ret;
 | 
			
		||||
	ShimattaOpenglProgramPrivate *priv;
 | 
			
		||||
 | 
			
		||||
	ret = g_object_new(SHIMATTA_TYPE_OPENGL_PROGRAM, NULL);
 | 
			
		||||
	priv = shimatta_opengl_program_get_instance_private(ret);
 | 
			
		||||
 | 
			
		||||
	priv->vertex_file = g_strdup(vertex_shader);
 | 
			
		||||
	priv->geometry_file = g_strdup(geometry_shader);
 | 
			
		||||
	priv->fragment_file = g_strdup(fragment_shader);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int shimatta_opengl_program_use(ShimattaOpenglProgram *program)
 | 
			
		||||
{
 | 
			
		||||
	ShimattaOpenglProgramPrivate *priv;
 | 
			
		||||
 | 
			
		||||
	g_return_val_if_fail(SHIMATTA_IS_OPENGL_PROGRAM(program), -1001);
 | 
			
		||||
 | 
			
		||||
	if (!shimatta_opengl_program_is_compiled(program))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	priv = shimatta_opengl_program_get_instance_private(program);
 | 
			
		||||
 | 
			
		||||
	glUseProgram(priv->shader_id);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean shimatta_opengl_program_is_compiled(ShimattaOpenglProgram *program)
 | 
			
		||||
{
 | 
			
		||||
	ShimattaOpenglProgramPrivate *priv;
 | 
			
		||||
 | 
			
		||||
	g_return_val_if_fail(SHIMATTA_IS_OPENGL_PROGRAM(program), FALSE);
 | 
			
		||||
	priv = shimatta_opengl_program_get_instance_private(program);
 | 
			
		||||
 | 
			
		||||
	return priv->compiled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *load_shader_from_source_file(const char *src_file)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int compile_shader(const char *src, char *error_text, size_t error_text_size, gboolean use_error,
 | 
			
		||||
			     GLuint shader_type, GLuint *shader_id_out)
 | 
			
		||||
{
 | 
			
		||||
	GLuint shader_id;
 | 
			
		||||
	GLint success;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	if (!shader_id_out || !src)
 | 
			
		||||
		return -1000;
 | 
			
		||||
 | 
			
		||||
	shader_id = glCreateShader(shader_type);
 | 
			
		||||
	glShaderSource(shader_id, 1, &src, NULL);
 | 
			
		||||
	glCompileShader(shader_id);
 | 
			
		||||
	glGetShaderiv(shader_id, GL_COMPILE_STATUS, &success);
 | 
			
		||||
 | 
			
		||||
	if (!success) {
 | 
			
		||||
		ret = -1;
 | 
			
		||||
		if (use_error) {
 | 
			
		||||
			glGetShaderInfoLog(shader_id, error_text_size, NULL, error_text);
 | 
			
		||||
		}
 | 
			
		||||
		glDeleteShader(shader_id);
 | 
			
		||||
	} else {
 | 
			
		||||
		*shader_id_out = shader_id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int shimatta_opengl_program_compile(ShimattaOpenglProgram *program, char *error_text, size_t error_text_size)
 | 
			
		||||
{
 | 
			
		||||
	gboolean use_error = FALSE;
 | 
			
		||||
	ShimattaOpenglProgramPrivate *priv;
 | 
			
		||||
	char *shader_source_code;
 | 
			
		||||
	int ret_val = 0;
 | 
			
		||||
	int status;
 | 
			
		||||
	GLint success;
 | 
			
		||||
	GLuint vertex_shader, fragment_shader, geometry_shader;
 | 
			
		||||
	gboolean vertex_built = FALSE, fragment_built = FALSE, geometry_built = FALSE;
 | 
			
		||||
 | 
			
		||||
	g_return_val_if_fail(SHIMATTA_IS_OPENGL_PROGRAM(program), -1001);
 | 
			
		||||
 | 
			
		||||
	if (error_text && error_text_size > 0)
 | 
			
		||||
		use_error = TRUE;
 | 
			
		||||
 | 
			
		||||
	priv = shimatta_opengl_program_get_instance_private(program);
 | 
			
		||||
 | 
			
		||||
	if (priv->compiled == TRUE) {
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	priv->shader_id = glCreateProgram();
 | 
			
		||||
 | 
			
		||||
	if (priv->vertex_src) {
 | 
			
		||||
		shader_source_code = priv->vertex_src;
 | 
			
		||||
	} else if (priv->vertex_file) {
 | 
			
		||||
		shader_source_code = load_shader_from_source_file(priv->vertex_file);
 | 
			
		||||
		if (!shader_source_code) {
 | 
			
		||||
			ret_val = -1;
 | 
			
		||||
			goto return_value;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	} else {
 | 
			
		||||
		shader_source_code = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Build the vertex shader */
 | 
			
		||||
	if (shader_source_code) {
 | 
			
		||||
		status = compile_shader(shader_source_code, error_text, error_text_size, use_error, GL_VERTEX_SHADER,
 | 
			
		||||
					&vertex_shader);
 | 
			
		||||
 | 
			
		||||
		free(shader_source_code);
 | 
			
		||||
 | 
			
		||||
		if (status) {
 | 
			
		||||
			ret_val = -2;
 | 
			
		||||
			goto return_value;
 | 
			
		||||
		}
 | 
			
		||||
		vertex_built = TRUE;
 | 
			
		||||
		glAttachShader(priv->shader_id, vertex_shader);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Build the fragment shader */
 | 
			
		||||
	if (priv->fragment_src) {
 | 
			
		||||
		shader_source_code = priv->fragment_src;
 | 
			
		||||
	} else if (priv->fragment_file) {
 | 
			
		||||
		shader_source_code = load_shader_from_source_file(priv->fragment_file);
 | 
			
		||||
		if (!shader_source_code) {
 | 
			
		||||
			ret_val = -1;
 | 
			
		||||
			goto return_value;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		shader_source_code = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (shader_source_code) {
 | 
			
		||||
		status = compile_shader(shader_source_code, error_text, error_text_size, use_error, GL_FRAGMENT_SHADER,
 | 
			
		||||
					&fragment_shader);
 | 
			
		||||
 | 
			
		||||
		free(shader_source_code);
 | 
			
		||||
 | 
			
		||||
		if (status) {
 | 
			
		||||
			ret_val = -2;
 | 
			
		||||
			goto return_value;
 | 
			
		||||
		}
 | 
			
		||||
		fragment_built = TRUE;
 | 
			
		||||
		glAttachShader(priv->shader_id, fragment_shader);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Build the geometry shader */
 | 
			
		||||
	if (priv->geometry_src) {
 | 
			
		||||
		shader_source_code = priv->geometry_src;
 | 
			
		||||
	} else if (priv->geometry_file) {
 | 
			
		||||
		shader_source_code = load_shader_from_source_file(priv->geometry_file);
 | 
			
		||||
		if (!shader_source_code) {
 | 
			
		||||
			ret_val = -1;
 | 
			
		||||
			goto return_value;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		shader_source_code = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (shader_source_code) {
 | 
			
		||||
		status = compile_shader(shader_source_code, error_text, error_text_size, use_error, GL_GEOMETRY_SHADER,
 | 
			
		||||
					&geometry_shader);
 | 
			
		||||
 | 
			
		||||
		free(shader_source_code);
 | 
			
		||||
 | 
			
		||||
		if (status) {
 | 
			
		||||
			ret_val = -2;
 | 
			
		||||
			goto return_value;
 | 
			
		||||
		}
 | 
			
		||||
		geometry_built = TRUE;
 | 
			
		||||
		glAttachShader(priv->shader_id, geometry_shader);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	glLinkProgram(priv->shader_id);
 | 
			
		||||
	glGetShaderiv(priv->shader_id, GL_LINK_STATUS, &success);
 | 
			
		||||
	if (!success) {
 | 
			
		||||
		if (use_error)
 | 
			
		||||
			glGetShaderInfoLog(priv->shader_id, error_text_size, NULL, error_text);
 | 
			
		||||
		ret_val = -3;
 | 
			
		||||
		glDeleteProgram(priv->shader_id);
 | 
			
		||||
	} else {
 | 
			
		||||
		priv->compiled = TRUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
return_value:
 | 
			
		||||
	if (vertex_built)
 | 
			
		||||
		glDeleteShader(vertex_shader);
 | 
			
		||||
	if (geometry_built)
 | 
			
		||||
		glDeleteShader(geometry_shader);
 | 
			
		||||
	if (fragment_built)
 | 
			
		||||
		glDeleteShader(fragment_shader);
 | 
			
		||||
 | 
			
		||||
	return ret_val;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user