[retro-gtk] Introduce RetroGLSLShader
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [retro-gtk] Introduce RetroGLSLShader
- Date: Sat, 23 May 2020 10:43:44 +0000 (UTC)
commit 991c103c72d64c531f6bde5ea90779dc50a88645
Author: Neville <nevilleantony98 gmail com>
Date: Sat May 23 13:38:50 2020 +0530
Introduce RetroGLSLShader
Currently shader specific code is integrated with RetroGLSLFilter.
RetroGLSLShader separates management of shaders from RetroGLSLFilters
and helps generalize code related to shaders.
doc/meson.build | 1 +
retro-gtk/meson.build | 1 +
retro-gtk/retro-glsl-shader-private.h | 39 ++++++
retro-gtk/retro-glsl-shader.c | 227 ++++++++++++++++++++++++++++++++++
4 files changed, 268 insertions(+)
---
diff --git a/doc/meson.build b/doc/meson.build
index 3fe17ea..b6e131c 100644
--- a/doc/meson.build
+++ b/doc/meson.build
@@ -13,6 +13,7 @@ private_headers = [
'retro-framebuffer-private.h',
'retro-gl-display-private.h',
'retro-glsl-filter-private.h',
+ 'retro-glsl-shader-private.h',
'retro-input-private.h',
'retro-keyboard-key-private.h',
'retro-keyboard-private.h',
diff --git a/retro-gtk/meson.build b/retro-gtk/meson.build
index ceb1dc7..2533605 100644
--- a/retro-gtk/meson.build
+++ b/retro-gtk/meson.build
@@ -32,6 +32,7 @@ retro_gtk_sources = [
'retro-core-view-controller.c',
'retro-gl-display.c',
'retro-glsl-filter.c',
+ 'retro-glsl-shader.c',
'retro-keyboard.c',
'retro-key-joypad-mapping.c',
'retro-log.c',
diff --git a/retro-gtk/retro-glsl-shader-private.h b/retro-gtk/retro-glsl-shader-private.h
new file mode 100644
index 0000000..675c71f
--- /dev/null
+++ b/retro-gtk/retro-glsl-shader-private.h
@@ -0,0 +1,39 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#pragma once
+
+#include <epoxy/gl.h>
+#include <gio/gio.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define RETRO_TYPE_GLSL_SHADER (retro_glsl_shader_get_type())
+
+G_DECLARE_FINAL_TYPE (RetroGLSLShader, retro_glsl_shader, RETRO, GLSL_SHADER, GObject)
+
+RetroGLSLShader *retro_glsl_shader_new (GBytes *vertex,
+ GBytes *fragment,
+ GLenum wrap,
+ GLenum filter,
+ GError **error);
+void retro_glsl_shader_use_program (RetroGLSLShader *self);
+void retro_glsl_shader_apply_texture_params (RetroGLSLShader *self);
+void retro_glsl_shader_set_attribute_pointer (RetroGLSLShader *self,
+ const gchar *name,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const GLvoid *pointer);
+void retro_glsl_shader_set_uniform_1f (RetroGLSLShader *self,
+ const gchar *name,
+ gfloat v0);
+void retro_glsl_shader_set_uniform_4f (RetroGLSLShader *self,
+ const gchar *name,
+ gfloat v0,
+ gfloat v1,
+ gfloat v2,
+ gfloat v3);
+
+G_END_DECLS
diff --git a/retro-gtk/retro-glsl-shader.c b/retro-gtk/retro-glsl-shader.c
new file mode 100644
index 0000000..f03ca58
--- /dev/null
+++ b/retro-gtk/retro-glsl-shader.c
@@ -0,0 +1,227 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#include "retro-glsl-shader-private.h"
+
+struct _RetroGLSLShader
+{
+ GObject parent_instance;
+ GBytes *vertex;
+ GBytes *fragment;
+ GLenum wrap;
+ GLenum filter;
+ GLuint program;
+};
+
+G_DEFINE_TYPE (RetroGLSLShader, retro_glsl_shader, G_TYPE_OBJECT)
+
+#define RETRO_GLSL_SHADER_ERROR (retro_glsl_shader_error_quark ())
+
+typedef enum {
+ RETRO_GLSL_SHADER_ERROR_COULDNT_COMPILE,
+ RETRO_GLSL_SHADER_ERROR_COULDNT_LINK
+} RetroGLSLShaderError;
+
+G_DEFINE_QUARK (retro-glsl-shader-error, retro_glsl_shader_error)
+
+static GLuint
+create_shader (GBytes *source_bytes,
+ GLenum shader_type,
+ GError **error)
+{
+ const gchar *source;
+ gint size;
+ GLuint shader;
+ gint status;
+
+ source = g_bytes_get_data (source_bytes, NULL);
+ size = g_bytes_get_size (source_bytes);
+ shader = glCreateShader (shader_type);
+ glShaderSource (shader, 1, &source, &size);
+ glCompileShader (shader);
+
+ glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ g_autofree gchar *buffer = NULL;
+ gint log_length;
+
+ 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_SHADER_ERROR, RETRO_GLSL_SHADER_ERROR_COULDNT_COMPILE,
+ "Compilation failure in %s shader: %s",
+ shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
+ buffer);
+
+ glDeleteShader (shader);
+
+ return 0;
+ }
+
+ return shader;
+}
+
+static void
+retro_glsl_shader_finalize (GObject *object)
+{
+ RetroGLSLShader *self = (RetroGLSLShader *) object;
+
+ if (self->program != 0) {
+ glDeleteProgram (self->program);
+ self->program = 0;
+ }
+
+ G_OBJECT_CLASS (retro_glsl_shader_parent_class)->finalize (object);
+}
+
+static void
+retro_glsl_shader_class_init (RetroGLSLShaderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = retro_glsl_shader_finalize;
+}
+
+static void
+retro_glsl_shader_init (RetroGLSLShader *self)
+{
+}
+
+RetroGLSLShader *
+retro_glsl_shader_new (GBytes *vertex,
+ GBytes *fragment,
+ GLenum wrap,
+ GLenum filter,
+ GError **error)
+{
+ g_autoptr (RetroGLSLShader) self = NULL;
+ gint status = 0;
+ GLuint vertex_shader;
+ GLuint fragment_shader;
+ GError *inner_error = NULL;
+
+ g_return_val_if_fail (vertex != NULL, NULL);
+ g_return_val_if_fail (fragment != NULL, NULL);
+ g_return_val_if_fail (wrap == GL_CLAMP_TO_BORDER || wrap == GL_CLAMP_TO_EDGE, NULL);
+ g_return_val_if_fail (filter == GL_LINEAR || filter == GL_NEAREST, NULL);
+
+ self = g_object_new (RETRO_TYPE_GLSL_SHADER, NULL);
+
+ self->vertex = vertex;
+ self->fragment = fragment;
+ self->wrap = wrap;
+ self->filter = filter;
+
+ vertex_shader = create_shader (self->vertex, GL_VERTEX_SHADER, &inner_error);
+ if (G_UNLIKELY (inner_error != NULL)) {
+ g_propagate_error (error, inner_error);
+
+ return NULL;
+ }
+
+ 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);
+
+ return NULL;
+ }
+
+ self->program = glCreateProgram ();
+ glAttachShader (self->program, vertex_shader);
+ glAttachShader (self->program, fragment_shader);
+ glLinkProgram (self->program);
+
+ glGetProgramiv (self->program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ gint log_length = 0;
+ g_autofree gchar *buffer;
+
+ 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_SHADER_ERROR, RETRO_GLSL_SHADER_ERROR_COULDNT_LINK,
+ "Linking failure in program: %s", buffer);
+
+ glDeleteShader (vertex_shader);
+ glDeleteShader (fragment_shader);
+
+ return NULL;
+ }
+
+ glDetachShader (self->program, vertex_shader);
+ glDetachShader (self->program, fragment_shader);
+
+ return g_steal_pointer (&self);
+}
+
+void
+retro_glsl_shader_use_program (RetroGLSLShader *self)
+{
+ g_return_if_fail (RETRO_IS_GLSL_SHADER (self));
+ g_return_if_fail (self->program != 0);
+
+ glUseProgram (self->program);
+}
+
+void
+retro_glsl_shader_apply_texture_params (RetroGLSLShader *self)
+{
+ g_return_if_fail (RETRO_IS_GLSL_SHADER (self));
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, self->wrap);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, self->wrap);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, self->filter);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, self->filter);
+}
+
+void
+retro_glsl_shader_set_attribute_pointer (RetroGLSLShader *self,
+ const gchar *name,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const GLvoid *pointer)
+{
+ GLint location;
+
+ g_return_if_fail (RETRO_IS_GLSL_SHADER (self));
+ g_return_if_fail (self->program != 0);
+
+ location = glGetAttribLocation (self->program, name);
+ glVertexAttribPointer (location, size, type, normalized, stride, pointer);
+ glEnableVertexAttribArray (location);
+}
+
+void
+retro_glsl_shader_set_uniform_1f (RetroGLSLShader *self,
+ const gchar *name,
+ gfloat v0)
+{
+ GLint location;
+
+ g_return_if_fail (RETRO_IS_GLSL_SHADER (self));
+ g_return_if_fail (self->program != 0);
+
+ location = glGetUniformLocation (self->program, name);
+ glUniform1f (location, v0);
+}
+
+void
+retro_glsl_shader_set_uniform_4f (RetroGLSLShader *self,
+ const gchar *name,
+ gfloat v0,
+ gfloat v1,
+ gfloat v2,
+ gfloat v3)
+{
+ GLint location;
+
+ g_return_if_fail (RETRO_IS_GLSL_SHADER (self));
+ g_return_if_fail (self->program != 0);
+
+ location = glGetUniformLocation (self->program, name);
+ glUniform4f (location, v0, v1, v2, v3);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]