mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-12 20:00:09 +00:00
32625381fa
The new renderers don't support them due to the required complexity of integrating them with Vulkan and the assumptions those nodes make about the renderer (the GL renderer exports its internal APIs into the GLShader). There haven't been any complaints that I'm aware of since 4.14 was released where the default renderer does not support the nodes, so usage in public seems to be close to nonexistant. The 2 uses I know of were workarounds about missing features in GTK that have stopped since GTK now supports them: 1. GStreamer used in to do premultiplication when the old GL renderer did not do so in hardware but on the CPU. 2. Adwaita used it for masking before the mask node wa added in 4.10.
310 lines
11 KiB
C
310 lines
11 KiB
C
/*
|
|
* Copyright © 2020 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Authors: Matthias Clasen <mclasen@redhat.com>
|
|
*/
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
|
|
|
/* shader fragment as found in nature */
|
|
const char shader0[] =
|
|
"// author: bobylito\n"
|
|
"// license: MIT\n"
|
|
"const float SQRT_2 = 1.414213562373;"
|
|
"uniform float dots;// = 20.0;"
|
|
"uniform vec2 center; //= vec2(0, 0);"
|
|
""
|
|
"vec4 transition(vec2 uv) {"
|
|
" bool nextImage = distance(fract(uv * dots), vec2(0.5, 0.5)) < ( progress / distance(uv, center));"
|
|
" return nextImage ? getToColor(uv) : getFromColor(uv);"
|
|
"}";
|
|
|
|
/* Same shader, with our preamble added, and with newlines
|
|
* to make the regex happy. Added a variety of uniforms to
|
|
* exercise the parser.
|
|
*/
|
|
const char shader1[] =
|
|
"uniform float progress;\n"
|
|
"uniform sampler2D u_texture1;\n"
|
|
"uniform sampler2D u_texture2;\n"
|
|
""
|
|
"vec4 getFromColor (vec2 uv) {\n"
|
|
" return GskTexture(u_texture1, uv);\n"
|
|
"}\n"
|
|
"\n"
|
|
"vec4 getToColor (vec2 uv) {\n"
|
|
" return GskTexture(u_texture2, uv);\n"
|
|
"}\n"
|
|
"\n"
|
|
"// author: bobylito\n"
|
|
"// license: MIT\n"
|
|
"const float SQRT_2 = 1.414213562373;\n"
|
|
"uniform float dots;// = 20.0;\n"
|
|
"uniform vec2 center; //= vec2(0, 0);\n"
|
|
"\n"
|
|
"uniform int test1 = -2;\n"
|
|
"uniform uint test2 = 2; \n"
|
|
"uniform bool test3;\n"
|
|
"uniform vec3 test4;\n"
|
|
"uniform vec4 test5;\n"
|
|
"\n"
|
|
"vec4 transition(vec2 uv) {\n"
|
|
" bool nextImage = distance(fract(uv * dots), vec2(0.5, 0.5)) < ( progress / distance(uv, center));\n"
|
|
" return nextImage ? getToColor(uv) : getFromColor(uv);\n"
|
|
"}\n"
|
|
"\n"
|
|
"void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)\n"
|
|
"{\n"
|
|
" fragColor = transition(uv);\n"
|
|
"}\n";
|
|
|
|
static void
|
|
test_create_simple (void)
|
|
{
|
|
GBytes *bytes;
|
|
GskGLShader *shader;
|
|
GBytes *source;
|
|
|
|
bytes = g_bytes_new_static (shader1, sizeof (shader1));
|
|
shader = gsk_gl_shader_new_from_bytes (bytes);
|
|
g_assert_nonnull (shader);
|
|
|
|
g_assert_cmpint (gsk_gl_shader_get_n_textures (shader), ==, 2);
|
|
g_assert_cmpint (gsk_gl_shader_get_n_uniforms (shader), ==, 8);
|
|
g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 0), ==, "progress");
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 0), ==, GSK_GL_UNIFORM_TYPE_FLOAT);
|
|
g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 1), ==, "dots");
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 1), ==, GSK_GL_UNIFORM_TYPE_FLOAT);
|
|
g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 2), ==, "center");
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 2), ==, GSK_GL_UNIFORM_TYPE_VEC2);
|
|
g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 3), ==, "test1");
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 3), ==, GSK_GL_UNIFORM_TYPE_INT);
|
|
g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 4), ==, "test2");
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 4), ==, GSK_GL_UNIFORM_TYPE_UINT);
|
|
g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 5), ==, "test3");
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 5), ==, GSK_GL_UNIFORM_TYPE_BOOL);
|
|
g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 6), ==, "test4");
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 6), ==, GSK_GL_UNIFORM_TYPE_VEC3);
|
|
g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 7), ==, "test5");
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 7), ==, GSK_GL_UNIFORM_TYPE_VEC4);
|
|
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "progress"), ==, 0);
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "dots"), ==, 1);
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "center"), ==, 2);
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test1"), ==, 3);
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test2"), ==, 4);
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test3"), ==, 5);
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test4"), ==, 6);
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test5"), ==, 7);
|
|
g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "nosucharg"), ==, -1);
|
|
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 0), ==, 0);
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 1), >, 0);
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 2), >, 0);
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 3), >, 0);
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 4), >, 0);
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 5), >, 0);
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 6), >, 0);
|
|
g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 7), >, 0);
|
|
|
|
g_assert_null (gsk_gl_shader_get_resource (shader));
|
|
|
|
g_object_get (shader, "source", &source, NULL);
|
|
g_assert_true (g_bytes_equal (source, bytes));
|
|
|
|
g_object_unref (shader);
|
|
g_bytes_unref (bytes);
|
|
g_bytes_unref (source);
|
|
}
|
|
|
|
static void
|
|
test_create_data (void)
|
|
{
|
|
GBytes *bytes;
|
|
GBytes *bytes2;
|
|
GskGLShader *shader;
|
|
GskShaderArgsBuilder *builder;
|
|
GskShaderArgsBuilder *builder2;
|
|
graphene_vec2_t v2, vv2;
|
|
graphene_vec3_t v3, vv3;
|
|
graphene_vec4_t v4, vv4;
|
|
GskRenderNode *node;
|
|
GskRenderNode *children[2];
|
|
|
|
bytes = g_bytes_new_static (shader1, sizeof (shader1));
|
|
shader = gsk_gl_shader_new_from_bytes (bytes);
|
|
g_assert_nonnull (shader);
|
|
g_clear_pointer (&bytes, g_bytes_unref);
|
|
|
|
builder = gsk_shader_args_builder_new (shader, NULL);
|
|
g_assert_nonnull (builder);
|
|
|
|
graphene_vec2_init (&v2, 20, 30);
|
|
graphene_vec3_init (&v3, -1, -2, -3);
|
|
graphene_vec4_init (&v4, 100, 0, -100, 10);
|
|
gsk_shader_args_builder_set_float (builder, 0, 0.5);
|
|
gsk_shader_args_builder_set_float (builder, 1, 20.0);
|
|
gsk_shader_args_builder_set_vec2 (builder, 2, &v2);
|
|
gsk_shader_args_builder_set_int (builder, 3, -99);
|
|
gsk_shader_args_builder_set_uint (builder, 4, 99);
|
|
gsk_shader_args_builder_set_bool (builder, 5, 1);
|
|
gsk_shader_args_builder_set_vec3 (builder, 6, &v3);
|
|
gsk_shader_args_builder_set_vec4 (builder, 7, &v4);
|
|
|
|
bytes = gsk_shader_args_builder_to_args (builder);
|
|
|
|
g_assert_cmpfloat (gsk_gl_shader_get_arg_float (shader, bytes, 0), ==, 0.5);
|
|
g_assert_cmpfloat (gsk_gl_shader_get_arg_float (shader, bytes, 1), ==, 20.0);
|
|
gsk_gl_shader_get_arg_vec2 (shader, bytes, 2, &vv2);
|
|
g_assert_true (graphene_vec2_equal (&v2, &vv2));
|
|
|
|
g_assert_cmpint (gsk_gl_shader_get_arg_int (shader, bytes, 3), ==, -99);
|
|
g_assert_cmpuint (gsk_gl_shader_get_arg_uint (shader, bytes, 4), ==, 99);
|
|
g_assert_cmpint (gsk_gl_shader_get_arg_bool (shader, bytes, 5), ==, 1);
|
|
|
|
gsk_gl_shader_get_arg_vec3 (shader, bytes, 6, &vv3);
|
|
g_assert_true (graphene_vec3_equal (&v3, &vv3));
|
|
gsk_gl_shader_get_arg_vec4 (shader, bytes, 7, &vv4);
|
|
g_assert_true (graphene_vec4_equal (&v4, &vv4));
|
|
|
|
children[0] = gsk_color_node_new (&(GdkRGBA){0,0,0,1}, &GRAPHENE_RECT_INIT (0, 0, 50, 50));
|
|
children[1] = gsk_color_node_new (&(GdkRGBA){1,0,0,1}, &GRAPHENE_RECT_INIT (0, 0, 50, 50));
|
|
node = gsk_gl_shader_node_new (shader,
|
|
&GRAPHENE_RECT_INIT (0, 0, 50, 50),
|
|
bytes,
|
|
children,
|
|
2);
|
|
|
|
g_assert_true (gsk_gl_shader_node_get_shader (node) == shader);
|
|
g_assert_cmpuint (gsk_gl_shader_node_get_n_children (node), ==, 2);
|
|
g_assert_true (gsk_gl_shader_node_get_child (node, 0) == children[0]);
|
|
g_assert_true (gsk_gl_shader_node_get_child (node, 1) == children[1]);
|
|
|
|
gsk_render_node_unref (children[0]);
|
|
gsk_render_node_unref (children[1]);
|
|
gsk_render_node_unref (node);
|
|
|
|
builder2 = gsk_shader_args_builder_new (shader, bytes);
|
|
gsk_shader_args_builder_ref (builder2);
|
|
bytes2 = gsk_shader_args_builder_free_to_args (builder2);
|
|
gsk_shader_args_builder_unref (builder2);
|
|
|
|
g_assert_true (g_bytes_equal (bytes, bytes2));
|
|
|
|
g_bytes_unref (bytes2);
|
|
g_bytes_unref (bytes);
|
|
|
|
gsk_shader_args_builder_unref (builder);
|
|
|
|
g_object_unref (shader);
|
|
}
|
|
|
|
static void
|
|
test_format_args (void)
|
|
{
|
|
GBytes *bytes;
|
|
GskGLShader *shader;
|
|
graphene_vec2_t v2, vv2;
|
|
graphene_vec3_t v3, vv3;
|
|
graphene_vec4_t v4, vv4;
|
|
float f1, f2;
|
|
GBytes *args;
|
|
|
|
bytes = g_bytes_new_static (shader1, sizeof (shader1));
|
|
shader = gsk_gl_shader_new_from_bytes (bytes);
|
|
g_assert_nonnull (shader);
|
|
g_clear_pointer (&bytes, g_bytes_unref);
|
|
|
|
graphene_vec2_init (&v2, 20, 30);
|
|
graphene_vec3_init (&v3, -1, -2, -3);
|
|
graphene_vec4_init (&v4, 100, 0, -100, 10);
|
|
|
|
f1 = 0.5;
|
|
f2 = 20.0;
|
|
args = gsk_gl_shader_format_args (shader,
|
|
"progress", f1,
|
|
"dots", f2,
|
|
"center", &v2,
|
|
"test4", &v3,
|
|
"test5", &v4,
|
|
NULL);
|
|
|
|
g_assert_cmpfloat (gsk_gl_shader_get_arg_float (shader, args, 0), ==, 0.5);
|
|
g_assert_cmpfloat (gsk_gl_shader_get_arg_float (shader, args, 1), ==, 20.0);
|
|
gsk_gl_shader_get_arg_vec2 (shader, args, 2, &vv2);
|
|
g_assert_true (graphene_vec2_equal (&v2, &vv2));
|
|
gsk_gl_shader_get_arg_vec3 (shader, args, 6, &vv3);
|
|
g_assert_true (graphene_vec3_equal (&v3, &vv3));
|
|
gsk_gl_shader_get_arg_vec4 (shader, args, 7, &vv4);
|
|
g_assert_true (graphene_vec4_equal (&v4, &vv4));
|
|
|
|
g_bytes_unref (args);
|
|
|
|
g_object_unref (shader);
|
|
}
|
|
|
|
static void
|
|
test_compile (void)
|
|
{
|
|
GBytes *bytes;
|
|
GskGLShader *shader;
|
|
GdkSurface *surface;
|
|
GskRenderer *renderer;
|
|
GError *error = NULL;
|
|
gboolean ret;
|
|
|
|
bytes = g_bytes_new_static ("blaat", 6);
|
|
shader = gsk_gl_shader_new_from_bytes (bytes);
|
|
g_assert_nonnull (shader);
|
|
|
|
surface = gdk_surface_new_toplevel (gdk_display_get_default ());
|
|
renderer = gsk_renderer_new_for_surface (surface);
|
|
g_assert_nonnull (renderer);
|
|
|
|
ret = gsk_gl_shader_compile (shader, renderer, &error);
|
|
|
|
g_assert_false (ret);
|
|
g_assert_nonnull (error);
|
|
if (g_str_equal (G_OBJECT_TYPE_NAME (renderer), "GskGLRenderer"))
|
|
g_assert_nonnull (strstr (error->message, "blaat"));
|
|
else
|
|
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
|
|
g_clear_error (&error);
|
|
|
|
gsk_renderer_unrealize (renderer);
|
|
g_object_unref (renderer);
|
|
gdk_surface_destroy (surface);
|
|
g_bytes_unref (bytes);
|
|
}
|
|
|
|
int
|
|
main (int argc,
|
|
char *argv[])
|
|
{
|
|
gtk_test_init (&argc, &argv, NULL);
|
|
|
|
g_test_add_func ("/shader/create/simple", test_create_simple);
|
|
g_test_add_func ("/shader/create/data", test_create_data);
|
|
g_test_add_func ("/shader/format-args", test_format_args);
|
|
g_test_add_func ("/shader/compile", test_compile);
|
|
|
|
return g_test_run ();
|
|
}
|
|
|
|
G_GNUC_END_IGNORE_DEPRECATIONS
|