1 /*
2 * GStreamer
3 * Copyright (C) 2016 Matthew Waters <matthew@centricular.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/gl/gstglfuncs.h>
26
27 #include "gstglutils.h"
28
29 struct _compile_shader
30 {
31 GstGLShader **shader;
32 const gchar *vertex_src;
33 const gchar *fragment_src;
34 };
35
36 static void
_compile_shader(GstGLContext * context,struct _compile_shader * data)37 _compile_shader (GstGLContext * context, struct _compile_shader *data)
38 {
39 GstGLShader *shader;
40 GstGLSLStage *vert, *frag;
41 GError *error = NULL;
42
43 shader = gst_gl_shader_new (context);
44
45 if (data->vertex_src) {
46 vert = gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
47 GST_GLSL_VERSION_NONE,
48 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, data->vertex_src);
49 if (!gst_glsl_stage_compile (vert, &error)) {
50 GST_ERROR_OBJECT (vert, "%s", error->message);
51 gst_object_unref (vert);
52 gst_object_unref (shader);
53 return;
54 }
55 if (!gst_gl_shader_attach (shader, vert)) {
56 gst_object_unref (shader);
57 return;
58 }
59 }
60
61 if (data->fragment_src) {
62 frag = gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
63 GST_GLSL_VERSION_NONE,
64 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
65 data->fragment_src);
66 if (!gst_glsl_stage_compile (frag, &error)) {
67 GST_ERROR_OBJECT (frag, "%s", error->message);
68 gst_object_unref (frag);
69 gst_object_unref (shader);
70 return;
71 }
72 if (!gst_gl_shader_attach (shader, frag)) {
73 gst_object_unref (shader);
74 return;
75 }
76 }
77
78 if (!gst_gl_shader_link (shader, &error)) {
79 GST_ERROR_OBJECT (shader, "%s", error->message);
80 g_error_free (error);
81 error = NULL;
82 gst_gl_context_clear_shader (context);
83 gst_object_unref (shader);
84 return;
85 }
86
87 *data->shader = shader;
88 }
89
90 /* Called by glfilter */
91 gboolean
gst_gl_context_gen_shader(GstGLContext * context,const gchar * vert_src,const gchar * frag_src,GstGLShader ** shader)92 gst_gl_context_gen_shader (GstGLContext * context, const gchar * vert_src,
93 const gchar * frag_src, GstGLShader ** shader)
94 {
95 struct _compile_shader data;
96
97 g_return_val_if_fail (frag_src != NULL || vert_src != NULL, FALSE);
98 g_return_val_if_fail (shader != NULL, FALSE);
99
100 data.shader = shader;
101 data.vertex_src = vert_src;
102 data.fragment_src = frag_src;
103
104 gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _compile_shader,
105 &data);
106
107 return *shader != NULL;
108 }
109