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 */
23const 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 */
39const 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
74static void
75test_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
107static void
108test_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
160static void
161test_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
204static void
205test_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
238int
239main (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

source code of gtk/testsuite/gsk/shader.c