1 | /* |
2 | * Copyright © 2020 Red Hat, Inc. |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | * |
17 | * Authors: Matthias Clasen <mclasen@redhat.com> |
18 | */ |
19 | |
20 | #include <gtk/gtk.h> |
21 | |
22 | /* shader fragment as found in nature */ |
23 | const char shader0[] = |
24 | "// author: bobylito\n" |
25 | "// license: MIT\n" |
26 | "const float SQRT_2 = 1.414213562373;" |
27 | "uniform float dots;// = 20.0;" |
28 | "uniform vec2 center; //= vec2(0, 0);" |
29 | "" |
30 | "vec4 transition(vec2 uv) {" |
31 | " bool nextImage = distance(fract(uv * dots), vec2(0.5, 0.5)) < ( progress / distance(uv, center));" |
32 | " return nextImage ? getToColor(uv) : getFromColor(uv);" |
33 | "}" ; |
34 | |
35 | /* Same shader, with our preamble added, and with newlines |
36 | * to make the regex happy. Added a variety of uniforms to |
37 | * exercise the parser. |
38 | */ |
39 | const char shader1[] = |
40 | "uniform float progress;\n" |
41 | "uniform sampler2D u_texture1;\n" |
42 | "uniform sampler2D u_texture2;\n" |
43 | "" |
44 | "vec4 getFromColor (vec2 uv) {\n" |
45 | " return GskTexture(u_texture1, uv);\n" |
46 | "}\n" |
47 | "\n" |
48 | "vec4 getToColor (vec2 uv) {\n" |
49 | " return GskTexture(u_texture2, uv);\n" |
50 | "}\n" |
51 | "\n" |
52 | "// author: bobylito\n" |
53 | "// license: MIT\n" |
54 | "const float SQRT_2 = 1.414213562373;\n" |
55 | "uniform float dots;// = 20.0;\n" |
56 | "uniform vec2 center; //= vec2(0, 0);\n" |
57 | "\n" |
58 | "uniform int test1 = -2;\n" |
59 | "uniform uint test2 = 2; \n" |
60 | "uniform bool test3;\n" |
61 | "uniform vec3 test4;\n" |
62 | "uniform vec4 test5;\n" |
63 | "\n" |
64 | "vec4 transition(vec2 uv) {\n" |
65 | " bool nextImage = distance(fract(uv * dots), vec2(0.5, 0.5)) < ( progress / distance(uv, center));\n" |
66 | " return nextImage ? getToColor(uv) : getFromColor(uv);\n" |
67 | "}\n" |
68 | "\n" |
69 | "void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)\n" |
70 | "{\n" |
71 | " fragColor = transition(uv);\n" |
72 | "}\n" ; |
73 | |
74 | static void |
75 | test_create_simple (void) |
76 | { |
77 | GBytes *bytes; |
78 | GskGLShader *shader; |
79 | |
80 | bytes = g_bytes_new_static (data: shader1, size: sizeof (shader1)); |
81 | shader = gsk_gl_shader_new_from_bytes (sourcecode: bytes); |
82 | g_assert_nonnull (shader); |
83 | |
84 | g_assert_cmpint (gsk_gl_shader_get_n_textures (shader), ==, 2); |
85 | g_assert_cmpint (gsk_gl_shader_get_n_uniforms (shader), ==, 8); |
86 | g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 0), ==, "progress" ); |
87 | g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 0), ==, GSK_GL_UNIFORM_TYPE_FLOAT); |
88 | g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 1), ==, "dots" ); |
89 | g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 1), ==, GSK_GL_UNIFORM_TYPE_FLOAT); |
90 | g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 2), ==, "center" ); |
91 | g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 2), ==, GSK_GL_UNIFORM_TYPE_VEC2); |
92 | g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 3), ==, "test1" ); |
93 | g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 3), ==, GSK_GL_UNIFORM_TYPE_INT); |
94 | g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 4), ==, "test2" ); |
95 | g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 4), ==, GSK_GL_UNIFORM_TYPE_UINT); |
96 | g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 5), ==, "test3" ); |
97 | g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 5), ==, GSK_GL_UNIFORM_TYPE_BOOL); |
98 | g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 6), ==, "test4" ); |
99 | g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 6), ==, GSK_GL_UNIFORM_TYPE_VEC3); |
100 | g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 7), ==, "test5" ); |
101 | g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 7), ==, GSK_GL_UNIFORM_TYPE_VEC4); |
102 | |
103 | g_object_unref (object: shader); |
104 | g_bytes_unref (bytes); |
105 | } |
106 | |
107 | static void |
108 | test_create_data (void) |
109 | { |
110 | GBytes *bytes; |
111 | GskGLShader *shader; |
112 | GskShaderArgsBuilder *builder; |
113 | graphene_vec2_t v2, vv2; |
114 | graphene_vec3_t v3, vv3; |
115 | graphene_vec4_t v4, vv4; |
116 | |
117 | bytes = g_bytes_new_static (data: shader1, size: sizeof (shader1)); |
118 | shader = gsk_gl_shader_new_from_bytes (sourcecode: bytes); |
119 | g_assert_nonnull (shader); |
120 | g_clear_pointer (&bytes, g_bytes_unref); |
121 | |
122 | builder = gsk_shader_args_builder_new (shader, NULL); |
123 | g_assert_nonnull (builder); |
124 | |
125 | graphene_vec2_init (v: &v2, x: 20, y: 30); |
126 | graphene_vec3_init (v: &v3, x: -1, y: -2, z: -3); |
127 | graphene_vec4_init (v: &v4, x: 100, y: 0, z: -100, w: 10); |
128 | gsk_shader_args_builder_set_float (builder, idx: 0, value: 0.5); |
129 | gsk_shader_args_builder_set_float (builder, idx: 1, value: 20.0); |
130 | gsk_shader_args_builder_set_vec2 (builder, idx: 2, value: &v2); |
131 | gsk_shader_args_builder_set_int (builder, idx: 3, value: -99); |
132 | gsk_shader_args_builder_set_uint (builder, idx: 4, value: 99); |
133 | gsk_shader_args_builder_set_bool (builder, idx: 5, value: 1); |
134 | gsk_shader_args_builder_set_vec3 (builder, idx: 6, value: &v3); |
135 | gsk_shader_args_builder_set_vec4 (builder, idx: 7, value: &v4); |
136 | |
137 | bytes = gsk_shader_args_builder_to_args (builder); |
138 | |
139 | g_assert_cmpfloat (gsk_gl_shader_get_arg_float (shader, bytes, 0), ==, 0.5); |
140 | g_assert_cmpfloat (gsk_gl_shader_get_arg_float (shader, bytes, 1), ==, 20.0); |
141 | gsk_gl_shader_get_arg_vec2 (shader, args: bytes, idx: 2, out_value: &vv2); |
142 | g_assert_true (graphene_vec2_equal (&v2, &vv2)); |
143 | |
144 | g_assert_cmpint (gsk_gl_shader_get_arg_int (shader, bytes, 3), ==, -99); |
145 | g_assert_cmpuint (gsk_gl_shader_get_arg_uint (shader, bytes, 4), ==, 99); |
146 | g_assert_cmpint (gsk_gl_shader_get_arg_bool (shader, bytes, 5), ==, 1); |
147 | |
148 | gsk_gl_shader_get_arg_vec3 (shader, args: bytes, idx: 6, out_value: &vv3); |
149 | g_assert_true (graphene_vec3_equal (&v3, &vv3)); |
150 | gsk_gl_shader_get_arg_vec4 (shader, args: bytes, idx: 7, out_value: &vv4); |
151 | g_assert_true (graphene_vec4_equal (&v4, &vv4)); |
152 | |
153 | g_bytes_unref (bytes); |
154 | |
155 | gsk_shader_args_builder_unref (builder); |
156 | |
157 | g_object_unref (object: shader); |
158 | } |
159 | |
160 | static void |
161 | test_format_args (void) |
162 | { |
163 | GBytes *bytes; |
164 | GskGLShader *shader; |
165 | graphene_vec2_t v2, vv2; |
166 | graphene_vec3_t v3, vv3; |
167 | graphene_vec4_t v4, vv4; |
168 | float f1, f2; |
169 | GBytes *args; |
170 | |
171 | bytes = g_bytes_new_static (data: shader1, size: sizeof (shader1)); |
172 | shader = gsk_gl_shader_new_from_bytes (sourcecode: bytes); |
173 | g_assert_nonnull (shader); |
174 | g_clear_pointer (&bytes, g_bytes_unref); |
175 | |
176 | graphene_vec2_init (v: &v2, x: 20, y: 30); |
177 | graphene_vec3_init (v: &v3, x: -1, y: -2, z: -3); |
178 | graphene_vec4_init (v: &v4, x: 100, y: 0, z: -100, w: 10); |
179 | |
180 | f1 = 0.5; |
181 | f2 = 20.0; |
182 | args = gsk_gl_shader_format_args (shader, |
183 | "progress" , f1, |
184 | "dots" , f2, |
185 | "center" , &v2, |
186 | "test4" , &v3, |
187 | "test5" , &v4, |
188 | NULL); |
189 | |
190 | g_assert_cmpfloat (gsk_gl_shader_get_arg_float (shader, args, 0), ==, 0.5); |
191 | g_assert_cmpfloat (gsk_gl_shader_get_arg_float (shader, args, 1), ==, 20.0); |
192 | gsk_gl_shader_get_arg_vec2 (shader, args, idx: 2, out_value: &vv2); |
193 | g_assert_true (graphene_vec2_equal (&v2, &vv2)); |
194 | gsk_gl_shader_get_arg_vec3 (shader, args, idx: 6, out_value: &vv3); |
195 | g_assert_true (graphene_vec3_equal (&v3, &vv3)); |
196 | gsk_gl_shader_get_arg_vec4 (shader, args, idx: 7, out_value: &vv4); |
197 | g_assert_true (graphene_vec4_equal (&v4, &vv4)); |
198 | |
199 | g_bytes_unref (bytes: args); |
200 | |
201 | g_object_unref (object: shader); |
202 | } |
203 | |
204 | static void |
205 | test_compile (void) |
206 | { |
207 | GBytes *bytes; |
208 | GskGLShader *shader; |
209 | GdkSurface *surface; |
210 | GskRenderer *renderer; |
211 | GError *error = NULL; |
212 | gboolean ret; |
213 | |
214 | bytes = g_bytes_new_static (data: "blaat" , size: 6); |
215 | shader = gsk_gl_shader_new_from_bytes (sourcecode: bytes); |
216 | g_assert_nonnull (shader); |
217 | |
218 | surface = gdk_surface_new_toplevel (display: gdk_display_get_default ()); |
219 | renderer = gsk_renderer_new_for_surface (surface); |
220 | g_assert_nonnull (renderer); |
221 | |
222 | ret = gsk_gl_shader_compile (shader, renderer, error: &error); |
223 | |
224 | g_assert_false (ret); |
225 | g_assert_nonnull (error); |
226 | if (g_str_equal (G_OBJECT_TYPE_NAME (renderer), v2: "GskGLRenderer" )) |
227 | g_assert_nonnull (strstr (error->message, "blaat" )); |
228 | else |
229 | g_error_matches (error, G_IO_ERROR, code: G_IO_ERROR_NOT_SUPPORTED); |
230 | g_clear_error (err: &error); |
231 | |
232 | gsk_renderer_unrealize (renderer); |
233 | g_object_unref (object: renderer); |
234 | g_object_unref (object: surface); |
235 | g_bytes_unref (bytes); |
236 | } |
237 | |
238 | int |
239 | main (int argc, |
240 | char *argv[]) |
241 | { |
242 | gtk_test_init (argcp: &argc, argvp: &argv, NULL); |
243 | |
244 | g_test_add_func (testpath: "/shader/create/simple" , test_func: test_create_simple); |
245 | g_test_add_func (testpath: "/shader/create/data" , test_func: test_create_data); |
246 | g_test_add_func (testpath: "/shader/format-args" , test_func: test_format_args); |
247 | g_test_add_func (testpath: "/shader/compile" , test_func: test_compile); |
248 | |
249 | return g_test_run (); |
250 | } |
251 | |