[retro-gtk] glsl-filter: Throw errors on program preparation
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [retro-gtk] glsl-filter: Throw errors on program preparation
- Date: Thu, 16 Nov 2017 12:54:30 +0000 (UTC)
commit e2697319c3adba51b73be400ecd8e0b774ab070c
Author: Adrien Plazas <kekun plazas laposte net>
Date: Thu Nov 16 11:42:35 2017 +0100
glsl-filter: Throw errors on program preparation
Also clean up the code code a bit more.
retro-gtk/retro-gl-display.c | 25 +++++++----
retro-gtk/retro-glsl-filter.c | 100 ++++++++++++++++++++++++++++++++++++-----
retro-gtk/retro-glsl-filter.h | 3 +-
3 files changed, 107 insertions(+), 21 deletions(-)
---
diff --git a/retro-gtk/retro-gl-display.c b/retro-gtk/retro-gl-display.c
index 34f5dc1..95d9f04 100644
--- a/retro-gtk/retro-gl-display.c
+++ b/retro-gtk/retro-gl-display.c
@@ -104,6 +104,7 @@ retro_gl_display_realize (RetroGLDisplay *self)
GLuint vertex_array_object;
GLuint element_buffer_object;
RetroVideoFilter filter;
+ GError *inner_error = NULL;
gtk_gl_area_make_current (GTK_GL_AREA (self));
@@ -120,7 +121,16 @@ retro_gl_display_realize (RetroGLDisplay *self)
for (filter = 0; filter < RETRO_VIDEO_FILTER_COUNT; filter++) {
self->glsl_filter[filter] = retro_glsl_filter_new (filter_uris[filter], NULL);
- retro_glsl_filter_prepare_program (self->glsl_filter[filter]);
+ retro_glsl_filter_prepare_program (self->glsl_filter[filter], &inner_error);
+ if (G_UNLIKELY (inner_error != NULL)) {
+ g_critical ("Shader program %s creation failed: %s",
+ filter_uris[filter],
+ inner_error->message);
+ g_clear_object (&self->glsl_filter[filter]);
+ g_clear_error (&inner_error);
+
+ continue;
+ }
retro_glsl_filter_set_attribute_pointer (self->glsl_filter[filter],
"position",
@@ -167,10 +177,6 @@ retro_gl_display_unrealize (RetroGLDisplay *self)
static gboolean
retro_gl_display_render (RetroGLDisplay *self)
{
- gdouble w = 0.0;
- gdouble h = 0.0;
- gdouble x = 0.0;
- gdouble y = 0.0;
GLfloat source_width, source_height;
GLfloat target_width, target_height;
GLfloat output_width, output_height;
@@ -178,19 +184,20 @@ retro_gl_display_render (RetroGLDisplay *self)
g_return_val_if_fail (self != NULL, FALSE);
- retro_gl_display_get_video_box (self, &w, &h, &x, &y);
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
filter = self->filter >= RETRO_VIDEO_FILTER_COUNT ?
RETRO_VIDEO_FILTER_SMOOTH :
self->filter;
- retro_glsl_filter_use_program (self->glsl_filter[filter]);
-
- glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ if (self->glsl_filter[filter] == NULL)
+ return FALSE;
if (self->pixbuf == NULL)
return FALSE;
+ retro_glsl_filter_use_program (self->glsl_filter[filter]);
+
glTexImage2D (GL_TEXTURE_2D,
0,
GL_RGB,
diff --git a/retro-gtk/retro-glsl-filter.c b/retro-gtk/retro-glsl-filter.c
index b82c0a4..9e1790b 100644
--- a/retro-gtk/retro-glsl-filter.c
+++ b/retro-gtk/retro-glsl-filter.c
@@ -9,8 +9,6 @@ struct _RetroGLSLFilter
GBytes *fragment;
GLenum wrap;
GLenum filter;
- GLuint vertex_shader;
- GLuint fragment_shader;
GLuint program;
};
@@ -18,6 +16,15 @@ G_DEFINE_TYPE (RetroGLSLFilter, retro_glsl_filter, G_TYPE_OBJECT)
#define GLSL_FILTER_GROUP "GLSL Filter"
+#define RETRO_GLSL_FILTER_ERROR (retro_glsl_filter_error_quark ())
+
+typedef enum {
+ RETRO_GLSL_FILTER_ERROR_SHADER_COMPILATION,
+ RETRO_GLSL_FILTER_ERROR_SHADER_LINK
+} RetroGLSLFilterError;
+
+G_DEFINE_QUARK (retro-glsl-filter-error, retro_glsl_filter_error)
+
static const gchar *
g_key_file_try_get_string (GKeyFile *key_file,
const gchar *group,
@@ -203,9 +210,8 @@ retro_glsl_filter_finalize (GObject *object)
g_bytes_unref (self->vertex);
if (self->fragment != NULL)
g_bytes_unref (self->fragment);
- glDeleteShader (self->vertex_shader);
- glDeleteShader (self->fragment_shader);
glDeleteProgram (self->program);
+ self->program = 0;
G_OBJECT_CLASS (retro_glsl_filter_parent_class)->finalize (object);
}
@@ -235,12 +241,16 @@ retro_glsl_filter_apply_texture_params (RetroGLSLFilter *self)
}
static GLuint
-create_shader (GBytes *source_bytes,
- GLenum shader_type)
+create_shader (GBytes *source_bytes,
+ GLenum shader_type,
+ GError **error)
{
const gchar *source;
gint size;
GLuint shader;
+ gint status;
+ gint log_length;
+ gchar *buffer;
source = g_bytes_get_data (source_bytes, NULL);
size = g_bytes_get_size (source_bytes);
@@ -248,27 +258,92 @@ create_shader (GBytes *source_bytes,
glShaderSource (shader, 1, &source, &size);
glCompileShader (shader);
+ status = 0;
+ glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &log_length);
+ buffer = g_malloc (log_length + 1);
+ glGetShaderInfoLog (shader, log_length, NULL, buffer);
+
+ g_set_error (error, RETRO_GLSL_FILTER_ERROR, RETRO_GLSL_FILTER_ERROR_SHADER_COMPILATION,
+ "Compilation failure in %s shader: %s",
+ shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
+ buffer);
+
+ g_free (buffer);
+ glDeleteShader (shader);
+
+ return 0;
+ }
+
return shader;
}
void
-retro_glsl_filter_prepare_program (RetroGLSLFilter *self)
+retro_glsl_filter_prepare_program (RetroGLSLFilter *self,
+ GError **error)
{
+ gint status;
+ gint log_length;
+ gchar *buffer;
+ GLuint vertex_shader;
+ GLuint fragment_shader;
+ GError *inner_error = NULL;
+
g_return_if_fail (RETRO_IS_GLSL_FILTER (self));
+ g_return_if_fail (self->program == 0);
- self->vertex_shader = create_shader (self->vertex, GL_VERTEX_SHADER);
- self->fragment_shader = create_shader (self->fragment, GL_FRAGMENT_SHADER);
+ vertex_shader = create_shader (self->vertex, GL_VERTEX_SHADER, &inner_error);
+ if (G_UNLIKELY (inner_error != NULL)) {
+ g_propagate_error (error, inner_error);
+ self->program = 0;
+
+ return;
+ }
+
+ fragment_shader = create_shader (self->fragment, GL_FRAGMENT_SHADER, &inner_error);
+ if (G_UNLIKELY (inner_error != NULL)) {
+ g_propagate_error (error, inner_error);
+ glDeleteShader (vertex_shader);
+ self->program = 0;
+
+ return;
+ }
self->program = glCreateProgram();
- glAttachShader (self->program, self->vertex_shader);
- glAttachShader (self->program, self->fragment_shader);
+ glAttachShader (self->program, vertex_shader);
+ glAttachShader (self->program, fragment_shader);
glLinkProgram (self->program);
+
+ status = 0;
+ glGetProgramiv (self->program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ log_length = 0;
+ glGetProgramiv (self->program, GL_INFO_LOG_LENGTH, &log_length);
+ buffer = g_malloc (log_length + 1);
+ glGetProgramInfoLog (self->program, log_length, NULL, buffer);
+
+ g_set_error (error, RETRO_GLSL_FILTER_ERROR, RETRO_GLSL_FILTER_ERROR_SHADER_LINK,
+ "Linking failure in program: %s", buffer);
+ g_free (buffer);
+
+ glDeleteShader (vertex_shader);
+ glDeleteShader (fragment_shader);
+ glDeleteProgram (self->program);
+ self->program = 0;
+
+ return;
+ }
+
+ glDetachShader (self->program, vertex_shader);
+ glDetachShader (self->program, fragment_shader);
}
void
retro_glsl_filter_use_program (RetroGLSLFilter *self)
{
g_return_if_fail (RETRO_IS_GLSL_FILTER (self));
+ g_return_if_fail (self->program != 0);
glUseProgram (self->program);
}
@@ -285,6 +360,7 @@ retro_glsl_filter_set_attribute_pointer (RetroGLSLFilter *self,
GLint location;
g_return_if_fail (RETRO_IS_GLSL_FILTER (self));
+ g_return_if_fail (self->program != 0);
location = glGetAttribLocation (self->program, name);
glVertexAttribPointer (location, size, type, normalized, stride, pointer);
@@ -300,6 +376,7 @@ retro_glsl_filter_set_uniform_1f (RetroGLSLFilter *self,
GLint location;
g_return_if_fail (RETRO_IS_GLSL_FILTER (self));
+ g_return_if_fail (self->program != 0);
location = glGetUniformLocation (self->program, name);
glUniform1f (location, v0);
@@ -316,6 +393,7 @@ retro_glsl_filter_set_uniform_4f (RetroGLSLFilter *self,
GLint location;
g_return_if_fail (RETRO_IS_GLSL_FILTER (self));
+ g_return_if_fail (self->program != 0);
location = glGetUniformLocation (self->program, name);
glUniform4f (location, v0, v1, v2, v3);
diff --git a/retro-gtk/retro-glsl-filter.h b/retro-gtk/retro-glsl-filter.h
index a9d0e11..d468626 100644
--- a/retro-gtk/retro-glsl-filter.h
+++ b/retro-gtk/retro-glsl-filter.h
@@ -14,7 +14,8 @@ G_DECLARE_FINAL_TYPE (RetroGLSLFilter, retro_glsl_filter, RETRO, GLSL_FILTER, GO
RetroGLSLFilter *retro_glsl_filter_new (const char *uri,
GError **error);
void retro_glsl_filter_apply_texture_params (RetroGLSLFilter *self);
-void retro_glsl_filter_prepare_program (RetroGLSLFilter *self);
+void retro_glsl_filter_prepare_program (RetroGLSLFilter *self,
+ GError **error);
void retro_glsl_filter_use_program (RetroGLSLFilter *self);
void retro_glsl_filter_set_attribute_pointer (RetroGLSLFilter *self,
const gchar *name,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]