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 program Shader Program
 | 
				
			||||||
 * @param error_text Error message from compilation. May be NULL.
 | 
					 * @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.
 | 
					 * @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);
 | 
					int shimatta_opengl_program_compile(ShimattaOpenglProgram *program, char *error_text, size_t error_text_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ struct _ShimattaOpenglProgram {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
	GLint shader_id;
 | 
						GLuint shader_id;
 | 
				
			||||||
	gboolean compiled;
 | 
						gboolean compiled;
 | 
				
			||||||
	char *fragment_file;
 | 
						char *fragment_file;
 | 
				
			||||||
	char *vertex_file;
 | 
						char *vertex_file;
 | 
				
			||||||
@@ -35,9 +35,42 @@ typedef struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
G_DEFINE_TYPE_WITH_PRIVATE(ShimattaOpenglProgram, shimatta_opengl_program, G_TYPE_OBJECT);
 | 
					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)
 | 
					static void shimatta_opengl_program_class_init(ShimattaOpenglProgramClass *klass)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	(void)klass;
 | 
						(void)klass;
 | 
				
			||||||
 | 
						GObjectClass *oclass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						oclass = G_OBJECT_CLASS(klass);
 | 
				
			||||||
 | 
						oclass->dispose = shimatta_opengl_program_dispose;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -73,3 +106,206 @@ ShimattaOpenglProgram *shimatta_opengl_program_new_from_data(const char *vertex_
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						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