Merge branch 'ngl-vertex-attributes' into 'master'

Ngl vertex attributes

See merge request GNOME/gtk!3290
This commit is contained in:
Matthias Clasen 2021-03-12 21:26:52 +00:00
commit 3e1524fade
28 changed files with 1526 additions and 246 deletions

View File

@ -13,7 +13,7 @@ static GtkWidget *window = NULL;
static GtkWidget *scrolledwindow;
static int selected;
#define N_WIDGET_TYPES 7
#define N_WIDGET_TYPES 8
static int hincrement = 5;
@ -110,6 +110,41 @@ populate_text (gboolean highlight)
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), textview);
}
static void
populate_emoji_text (void)
{
GtkWidget *textview;
GtkTextBuffer *buffer;
GString *s;
s = g_string_sized_new (1000 * 30 * 4);
for (int i = 0; i < 1000; i++)
{
if (i % 2)
g_string_append (s, "x");
for (int j = 0; j < 30; j++)
g_string_append (s, "💓x");
g_string_append (s, "\n");
}
buffer = gtk_text_buffer_new (NULL);
gtk_text_buffer_set_text (buffer, s->str, s->len);
g_string_free (s, TRUE);
textview = gtk_text_view_new ();
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), textview);
}
static void
populate_image (void)
{
@ -224,21 +259,26 @@ set_widget_type (int type)
break;
case 3:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling text with Emoji");
populate_emoji_text ();
break;
case 4:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a big image");
populate_image ();
break;
case 4:
case 5:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a list");
populate_list ();
break;
case 5:
case 6:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a columned list");
populate_list2 ();
break;
case 6:
case 7:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a grid");
populate_grid ();
break;

View File

@ -20,13 +20,17 @@ def replace_if_changed(new, old):
else:
os.remove(new)
source_shaders = []
gl_source_shaders = []
ngl_source_shaders = []
vulkan_compiled_shaders = []
vulkan_shaders = []
for f in sys.argv[2:]:
if f.endswith('.glsl'):
source_shaders.append(f)
if f.startswith('ngl'):
ngl_source_shaders.append(f);
else:
gl_source_shaders.append(f)
elif f.endswith('.spv'):
vulkan_compiled_shaders.append(f)
elif f.endswith('.frag') or f.endswith('.vert'):
@ -40,11 +44,16 @@ xml = '''<?xml version='1.0' encoding='UTF-8'?>
'''
for f in source_shaders:
for f in gl_source_shaders:
xml += ' <file alias=\'glsl/{0}\'>resources/glsl/{0}</file>\n'.format(os.path.basename(f))
xml += '\n'
for f in ngl_source_shaders:
xml += ' <file alias=\'ngl/{0}\'>ngl/resources/{0}</file>\n'.format(os.path.basename(f))
xml += '\n'
for f in vulkan_compiled_shaders:
xml += ' <file alias=\'vulkan/{0}\'>resources/vulkan/{0}</file>\n'.format(os.path.basename(f))

View File

@ -20,6 +20,28 @@ gsk_private_gl_shaders = [
'resources/glsl/custom.glsl',
]
gsk_private_ngl_shaders = [
'ngl/resources/preamble.glsl',
'ngl/resources/preamble.fs.glsl',
'ngl/resources/preamble.vs.glsl',
'ngl/resources/border.glsl',
'ngl/resources/blit.glsl',
'ngl/resources/coloring.glsl',
'ngl/resources/color.glsl',
'ngl/resources/linear_gradient.glsl',
'ngl/resources/radial_gradient.glsl',
'ngl/resources/conic_gradient.glsl',
'ngl/resources/color_matrix.glsl',
'ngl/resources/blur.glsl',
'ngl/resources/inset_shadow.glsl',
'ngl/resources/outset_shadow.glsl',
'ngl/resources/unblurred_outset_shadow.glsl',
'ngl/resources/cross_fade.glsl',
'ngl/resources/blend.glsl',
'ngl/resources/repeat.glsl',
'ngl/resources/custom.glsl',
]
gsk_public_sources = files([
'gskdiff.c',
'gskcairorenderer.c',
@ -150,6 +172,7 @@ gsk_resources_xml = configure_file(output: 'gsk.resources.xml',
find_program('gen-gsk-gresources-xml.py'),
'@OUTPUT@',
gsk_private_gl_shaders,
gsk_private_ngl_shaders,
gsk_private_vulkan_compiled_shaders,
gsk_private_vulkan_shaders
],

View File

@ -1096,6 +1096,12 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue *self,
sizeof (GskNglDrawVertex),
(void *) G_STRUCT_OFFSET (GskNglDrawVertex, uv));
/* 2 = color location */
glEnableVertexAttribArray (2);
glVertexAttribPointer (2, 4, GL_FLOAT, GL_FALSE,
sizeof (GskNglDrawVertex),
(void *) G_STRUCT_OFFSET (GskNglDrawVertex, color));
/* Setup initial scissor clip */
if (scissor != NULL)
{

View File

@ -336,17 +336,18 @@ gsk_ngl_driver_load_programs (GskNglDriver *self,
/* Setup preambles that are shared by all shaders */
gsk_ngl_compiler_set_preamble_from_resource (compiler,
GSK_NGL_COMPILER_ALL,
"/org/gtk/libgsk/glsl/preamble.glsl");
"/org/gtk/libgsk/ngl/preamble.glsl");
gsk_ngl_compiler_set_preamble_from_resource (compiler,
GSK_NGL_COMPILER_VERTEX,
"/org/gtk/libgsk/glsl/preamble.vs.glsl");
"/org/gtk/libgsk/ngl/preamble.vs.glsl");
gsk_ngl_compiler_set_preamble_from_resource (compiler,
GSK_NGL_COMPILER_FRAGMENT,
"/org/gtk/libgsk/glsl/preamble.fs.glsl");
"/org/gtk/libgsk/ngl/preamble.fs.glsl");
/* Setup attributes that are provided via VBO */
gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0);
gsk_ngl_compiler_bind_attribute (compiler, "aUv", 1);
gsk_ngl_compiler_bind_attribute (compiler, "aColor", 2);
/* Use XMacros to register all of our programs and their uniforms */
#define GSK_NGL_NO_UNIFORMS
@ -376,7 +377,6 @@ gsk_ngl_driver_load_programs (GskNglDriver *self,
uniforms \
\
gsk_ngl_program_uniforms_added (program, have_source); \
\
if (have_alpha) \
gsk_ngl_program_set_uniform1f (program, UNIFORM_SHARED_ALPHA, 0, 1.0f); \
\
@ -1045,6 +1045,7 @@ gsk_ngl_driver_lookup_shader (GskNglDriver *self,
/* Setup attributes that are provided via VBO */
gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0);
gsk_ngl_compiler_bind_attribute (compiler, "aUv", 1);
gsk_ngl_compiler_bind_attribute (compiler, "aColor", 2);
if ((program = gsk_ngl_compiler_compile (compiler, NULL, "", error)))
{

View File

@ -58,13 +58,17 @@ typedef struct {
graphene_rect_t parent_rect; /* Valid when pointer_is_child */
} GskTextureKey;
#define GSL_GK_NO_UNIFORMS UNIFORM_INVALID_##__COUNTER__
#define GSK_NGL_NO_UNIFORMS CONCAT_EXPANDED(UNIFORM_INVALID_,__COUNTER__)
#define CONCAT_EXPANDED(a,b) CONCAT_EXPANDED2(a,b)
#define CONCAT_EXPANDED2(a,b) a##b
#define GSK_NGL_ADD_UNIFORM(pos, KEY, name) UNIFORM_##KEY = UNIFORM_SHARED_LAST + pos,
#define GSK_NGL_DEFINE_PROGRAM(name, resource, uniforms) enum { uniforms };
# include "gsknglprograms.defs"
#undef GSK_NGL_DEFINE_PROGRAM
#undef GSK_NGL_ADD_UNIFORM
#undef GSL_GK_NO_UNIFORMS
#undef GSK_NGL_NO_UNIFORMS
#undef CONCAT_EXPANDED
#undef CONCAT_EXPANDED2
#define GSK_TYPE_NGL_DRIVER (gsk_ngl_driver_get_type())

View File

@ -1,69 +1,66 @@
GSK_NGL_DEFINE_PROGRAM (blend,
"/org/gtk/libgsk/glsl/blend.glsl",
"/org/gtk/libgsk/ngl/blend.glsl",
GSK_NGL_ADD_UNIFORM (1, BLEND_SOURCE2, u_source2)
GSK_NGL_ADD_UNIFORM (2, BLEND_MODE, u_mode))
GSK_NGL_DEFINE_PROGRAM (blit,
"/org/gtk/libgsk/glsl/blit.glsl",
"/org/gtk/libgsk/ngl/blit.glsl",
GSK_NGL_NO_UNIFORMS)
GSK_NGL_DEFINE_PROGRAM (blur,
"/org/gtk/libgsk/glsl/blur.glsl",
"/org/gtk/libgsk/ngl/blur.glsl",
GSK_NGL_ADD_UNIFORM (1, BLUR_RADIUS, u_blur_radius)
GSK_NGL_ADD_UNIFORM (2, BLUR_SIZE, u_blur_size)
GSK_NGL_ADD_UNIFORM (3, BLUR_DIR, u_blur_dir))
GSK_NGL_DEFINE_PROGRAM (border,
"/org/gtk/libgsk/glsl/border.glsl",
GSK_NGL_ADD_UNIFORM (1, BORDER_COLOR, u_color)
"/org/gtk/libgsk/ngl/border.glsl",
GSK_NGL_ADD_UNIFORM (2, BORDER_WIDTHS, u_widths)
GSK_NGL_ADD_UNIFORM (3, BORDER_OUTLINE_RECT, u_outline_rect))
GSK_NGL_DEFINE_PROGRAM (color,
"/org/gtk/libgsk/glsl/color.glsl",
GSK_NGL_ADD_UNIFORM (1, COLOR_COLOR, u_color))
"/org/gtk/libgsk/ngl/color.glsl",
GSK_NGL_NO_UNIFORMS)
GSK_NGL_DEFINE_PROGRAM (coloring,
"/org/gtk/libgsk/glsl/coloring.glsl",
GSK_NGL_ADD_UNIFORM (1, COLORING_COLOR, u_color))
"/org/gtk/libgsk/ngl/coloring.glsl",
GSK_NGL_NO_UNIFORMS)
GSK_NGL_DEFINE_PROGRAM (color_matrix,
"/org/gtk/libgsk/glsl/color_matrix.glsl",
"/org/gtk/libgsk/ngl/color_matrix.glsl",
GSK_NGL_ADD_UNIFORM (1, COLOR_MATRIX_COLOR_MATRIX, u_color_matrix)
GSK_NGL_ADD_UNIFORM (2, COLOR_MATRIX_COLOR_OFFSET, u_color_offset))
GSK_NGL_DEFINE_PROGRAM (conic_gradient,
"/org/gtk/libgsk/glsl/conic_gradient.glsl",
"/org/gtk/libgsk/ngl/conic_gradient.glsl",
GSK_NGL_ADD_UNIFORM (1, CONIC_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_NGL_ADD_UNIFORM (2, CONIC_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_NGL_ADD_UNIFORM (3, CONIC_GRADIENT_GEOMETRY, u_geometry))
GSK_NGL_DEFINE_PROGRAM (cross_fade,
"/org/gtk/libgsk/glsl/cross_fade.glsl",
"/org/gtk/libgsk/ngl/cross_fade.glsl",
GSK_NGL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress)
GSK_NGL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2))
GSK_NGL_DEFINE_PROGRAM (inset_shadow,
"/org/gtk/libgsk/glsl/inset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (1, INSET_SHADOW_COLOR, u_color)
"/org/gtk/libgsk/ngl/inset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (2, INSET_SHADOW_SPREAD, u_spread)
GSK_NGL_ADD_UNIFORM (3, INSET_SHADOW_OFFSET, u_offset)
GSK_NGL_ADD_UNIFORM (4, INSET_SHADOW_OUTLINE_RECT, u_outline_rect))
GSK_NGL_DEFINE_PROGRAM (linear_gradient,
"/org/gtk/libgsk/glsl/linear_gradient.glsl",
"/org/gtk/libgsk/ngl/linear_gradient.glsl",
GSK_NGL_ADD_UNIFORM (1, LINEAR_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_NGL_ADD_UNIFORM (2, LINEAR_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_NGL_ADD_UNIFORM (3, LINEAR_GRADIENT_POINTS, u_points)
GSK_NGL_ADD_UNIFORM (4, LINEAR_GRADIENT_REPEAT, u_repeat))
GSK_NGL_DEFINE_PROGRAM (outset_shadow,
"/org/gtk/libgsk/glsl/outset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (1, OUTSET_SHADOW_COLOR, u_color)
"/org/gtk/libgsk/ngl/outset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (2, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
GSK_NGL_DEFINE_PROGRAM (radial_gradient,
"/org/gtk/libgsk/glsl/radial_gradient.glsl",
"/org/gtk/libgsk/ngl/radial_gradient.glsl",
GSK_NGL_ADD_UNIFORM (1, RADIAL_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_NGL_ADD_UNIFORM (2, RADIAL_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_NGL_ADD_UNIFORM (3, RADIAL_GRADIENT_REPEAT, u_repeat)
@ -71,13 +68,12 @@ GSK_NGL_DEFINE_PROGRAM (radial_gradient,
GSK_NGL_ADD_UNIFORM (5, RADIAL_GRADIENT_GEOMETRY, u_geometry))
GSK_NGL_DEFINE_PROGRAM (repeat,
"/org/gtk/libgsk/glsl/repeat.glsl",
"/org/gtk/libgsk/ngl/repeat.glsl",
GSK_NGL_ADD_UNIFORM (1, REPEAT_CHILD_BOUNDS, u_child_bounds)
GSK_NGL_ADD_UNIFORM (2, REPEAT_TEXTURE_RECT, u_texture_rect))
GSK_NGL_DEFINE_PROGRAM (unblurred_outset_shadow,
"/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_COLOR, u_color)
"/org/gtk/libgsk/ngl/unblurred_outset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
GSK_NGL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
GSK_NGL_ADD_UNIFORM (4, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))

View File

@ -142,6 +142,9 @@ struct _GskNglRenderJob
/* Our current alpha state as we process nodes */
float alpha;
/* Our current color state as we process nodes */
GdkRGBA color;
/* Offset (delta x,y) as we process nodes. Occasionally this is merged into
* a transform that is referenced from child transform nodes.
*/
@ -395,6 +398,13 @@ gsk_ngl_render_job_set_alpha (GskNglRenderJob *job,
return alpha;
}
static inline void
gsk_ngl_render_job_set_color (GskNglRenderJob *job,
const GdkRGBA *color)
{
job->color = *color;
}
static void
extract_matrix_metadata (GskNglRenderModelview *modelview)
{
@ -874,13 +884,81 @@ gsk_ngl_render_job_update_clip (GskNglRenderJob *job,
return TRUE;
}
/* fill_vertex_data */
static void
gsk_ngl_render_job_draw_coords (GskNglRenderJob *job,
float min_x,
float min_y,
float max_x,
float max_y,
float min_u,
float min_v,
float max_u,
float max_v)
{
GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue);
vertices[0].position[0] = min_x;
vertices[0].position[1] = min_y;
vertices[0].uv[0] = min_u;
vertices[0].uv[1] = min_v;
vertices[0].color[0] = job->color.red;
vertices[0].color[1] = job->color.green;
vertices[0].color[2] = job->color.blue;
vertices[0].color[3] = job->color.alpha;
vertices[1].position[0] = min_x;
vertices[1].position[1] = max_y;
vertices[1].uv[0] = min_u;
vertices[1].uv[1] = max_v;
vertices[1].color[0] = job->color.red;
vertices[1].color[1] = job->color.green;
vertices[1].color[2] = job->color.blue;
vertices[1].color[3] = job->color.alpha;
vertices[2].position[0] = max_x;
vertices[2].position[1] = min_y;
vertices[2].uv[0] = max_u;
vertices[2].uv[1] = min_v;
vertices[2].color[0] = job->color.red;
vertices[2].color[1] = job->color.green;
vertices[2].color[2] = job->color.blue;
vertices[2].color[3] = job->color.alpha;
vertices[3].position[0] = max_x;
vertices[3].position[1] = max_y;
vertices[3].uv[0] = max_u;
vertices[3].uv[1] = max_v;
vertices[3].color[0] = job->color.red;
vertices[3].color[1] = job->color.green;
vertices[3].color[2] = job->color.blue;
vertices[3].color[3] = job->color.alpha;
vertices[4].position[0] = min_x;
vertices[4].position[1] = max_y;
vertices[4].uv[0] = min_u;
vertices[4].uv[1] = max_v;
vertices[4].color[0] = job->color.red;
vertices[4].color[1] = job->color.green;
vertices[4].color[2] = job->color.blue;
vertices[4].color[3] = job->color.alpha;
vertices[5].position[0] = max_x;
vertices[5].position[1] = min_y;
vertices[5].uv[0] = max_u;
vertices[5].uv[1] = min_v;
vertices[5].color[0] = job->color.red;
vertices[5].color[1] = job->color.green;
vertices[5].color[2] = job->color.blue;
vertices[5].color[3] = job->color.alpha;
}
/* load_vertex_data_with_region */
static inline void
gsk_ngl_render_job_load_vertices_from_offscreen (GskNglRenderJob *job,
const graphene_rect_t *bounds,
const GskNglRenderOffscreen *offscreen)
{
GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue);
float min_x = job->offset_x + bounds->origin.x;
float min_y = job->offset_y + bounds->origin.y;
float max_x = min_x + bounds->size.width;
@ -888,35 +966,9 @@ gsk_ngl_render_job_load_vertices_from_offscreen (GskNglRenderJob *jo
float y1 = offscreen->was_offscreen ? offscreen->area.y2 : offscreen->area.y;
float y2 = offscreen->was_offscreen ? offscreen->area.y : offscreen->area.y2;
vertices[0].position[0] = min_x;
vertices[0].position[1] = min_y;
vertices[0].uv[0] = offscreen->area.x;
vertices[0].uv[1] = y1;
vertices[1].position[0] = min_x;
vertices[1].position[1] = max_y;
vertices[1].uv[0] = offscreen->area.x;
vertices[1].uv[1] = y2;
vertices[2].position[0] = max_x;
vertices[2].position[1] = min_y;
vertices[2].uv[0] = offscreen->area.x2;
vertices[2].uv[1] = y1;
vertices[3].position[0] = max_x;
vertices[3].position[1] = max_y;
vertices[3].uv[0] = offscreen->area.x2;
vertices[3].uv[1] = y2;
vertices[4].position[0] = min_x;
vertices[4].position[1] = max_y;
vertices[4].uv[0] = offscreen->area.x;
vertices[4].uv[1] = y2;
vertices[5].position[0] = max_x;
vertices[5].position[1] = min_y;
vertices[5].uv[0] = offscreen->area.x2;
vertices[5].uv[1] = y1;
gsk_ngl_render_job_draw_coords (job,
min_x, min_y, max_x, max_y,
offscreen->area.x, y1, offscreen->area.x2, y2);
}
/* load_float_vertex_data */
@ -927,41 +979,12 @@ gsk_ngl_render_job_draw (GskNglRenderJob *job,
float width,
float height)
{
GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue);
float min_x = job->offset_x + x;
float min_y = job->offset_y + y;
float max_x = min_x + width;
float max_y = min_y + height;
vertices[0].position[0] = min_x;
vertices[0].position[1] = min_y;
vertices[0].uv[0] = 0;
vertices[0].uv[1] = 0;
vertices[1].position[0] = min_x;
vertices[1].position[1] = max_y;
vertices[1].uv[0] = 0;
vertices[1].uv[1] = 1;
vertices[2].position[0] = max_x;
vertices[2].position[1] = min_y;
vertices[2].uv[0] = 1;
vertices[2].uv[1] = 0;
vertices[3].position[0] = max_x;
vertices[3].position[1] = max_y;
vertices[3].uv[0] = 1;
vertices[3].uv[1] = 1;
vertices[4].position[0] = min_x;
vertices[4].position[1] = max_y;
vertices[4].uv[0] = 0;
vertices[4].uv[1] = 1;
vertices[5].position[0] = max_x;
vertices[5].position[1] = min_y;
vertices[5].uv[0] = 1;
vertices[5].uv[1] = 0;
gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 0, 1, 1);
}
/* load_vertex_data */
@ -976,47 +999,6 @@ gsk_ngl_render_job_draw_rect (GskNglRenderJob *job,
bounds->size.height);
}
/* fill_vertex_data */
static void
gsk_ngl_render_job_draw_coords (GskNglRenderJob *job,
float min_x,
float min_y,
float max_x,
float max_y)
{
GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue);
vertices[0].position[0] = min_x;
vertices[0].position[1] = min_y;
vertices[0].uv[0] = 0;
vertices[0].uv[1] = 1;
vertices[1].position[0] = min_x;
vertices[1].position[1] = max_y;
vertices[1].uv[0] = 0;
vertices[1].uv[1] = 0;
vertices[2].position[0] = max_x;
vertices[2].position[1] = min_y;
vertices[2].uv[0] = 1;
vertices[2].uv[1] = 1;
vertices[3].position[0] = max_x;
vertices[3].position[1] = max_y;
vertices[3].uv[0] = 1;
vertices[3].uv[1] = 0;
vertices[4].position[0] = min_x;
vertices[4].position[1] = max_y;
vertices[4].uv[0] = 0;
vertices[4].uv[1] = 0;
vertices[5].position[0] = max_x;
vertices[5].position[1] = min_y;
vertices[5].uv[0] = 1;
vertices[5].uv[1] = 1;
}
/* load_offscreen_vertex_data */
static inline void
gsk_ngl_render_job_draw_offscreen_rect (GskNglRenderJob *job,
@ -1027,7 +1009,7 @@ gsk_ngl_render_job_draw_offscreen_rect (GskNglRenderJob *job,
float max_x = min_x + bounds->size.width;
float max_y = min_y + bounds->size.height;
gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y);
gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 1, 1, 0);
}
static inline void
@ -1283,7 +1265,7 @@ blur_offscreen (GskNglRenderJob *job,
gsk_ngl_program_set_uniform2f (job->current_program,
UNIFORM_BLUR_DIR, 0,
1, 0);
gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height);
gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height, 0, 1, 1, 0);
gsk_ngl_render_job_end_draw (job);
/* Bind second pass framebuffer and clear it */
@ -1307,7 +1289,7 @@ blur_offscreen (GskNglRenderJob *job,
gsk_ngl_program_set_uniform2f (job->current_program,
UNIFORM_BLUR_DIR, 0,
0, 1);
gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height);
gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height, 0, 1, 1, 0);
gsk_ngl_render_job_end_draw (job);
gsk_ngl_render_job_pop_modelview (job);
@ -1381,9 +1363,7 @@ gsk_ngl_render_job_visit_color_node (GskNglRenderJob *job,
const GskRenderNode *node)
{
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color));
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_COLOR_COLOR, 0,
gsk_color_node_get_color (node));
gsk_ngl_render_job_set_color (job, gsk_color_node_get_color (node));
gsk_ngl_render_job_draw_rect (job, &node->bounds);
gsk_ngl_render_job_end_draw (job);
}
@ -1694,9 +1674,7 @@ gsk_ngl_render_job_visit_rect_border_node (GskNglRenderJob *job,
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color));
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_COLOR_COLOR, 0,
&colors[0]);
gsk_ngl_render_job_set_color (job, &colors[0]);
gsk_ngl_render_job_draw_rect (job,
&GRAPHENE_RECT_INIT (origin->x,
@ -1737,12 +1715,10 @@ gsk_ngl_render_job_visit_uniform_border_node (GskNglRenderJob *job,
gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
gsk_ngl_render_job_set_color (job, &colors[0]);
gsk_ngl_program_set_uniform_rounded_rect (job->current_program,
UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0,
&outline);
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_INSET_SHADOW_COLOR, 0,
&colors[0]);
gsk_ngl_program_set_uniform1f (job->current_program,
UNIFORM_INSET_SHADOW_SPREAD, 0,
widths[0]);
@ -1758,7 +1734,7 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob *job,
const GskRenderNode *node)
{
const GskRoundedRect *rounded_outline = gsk_border_node_get_outline (node);
const GdkRGBA *colors = gsk_border_node_get_colors (node);
const GdkRGBA *c = gsk_border_node_get_colors (node);
const float *widths = gsk_border_node_get_widths (node);
struct {
float w;
@ -1818,52 +1794,48 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob *job,
const GskNglDrawVertex side_data[4][6] = {
/* Top */
{
{ { min_x, min_y }, { 0, 1 }, }, /* Upper left */
{ { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, }, /* Lower left */
{ { max_x, min_y }, { 1, 1 }, }, /* Upper right */
{ { min_x, min_y }, { 0, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper left */
{ { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower left */
{ { max_x, min_y }, { 1, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper right */
{ { max_x - sizes[1].w, min_y + sizes[1].h }, { 1, 0 }, }, /* Lower right */
{ { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, }, /* Lower left */
{ { max_x, min_y }, { 1, 1 }, }, /* Upper right */
{ { max_x - sizes[1].w, min_y + sizes[1].h }, { 1, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower right */
{ { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower left */
{ { max_x, min_y }, { 1, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper right */
},
/* Right */
{
{ { max_x - sizes[1].w, min_y + sizes[1].h }, { 0, 1 }, }, /* Upper left */
{ { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, }, /* Lower left */
{ { max_x, min_y }, { 1, 1 }, }, /* Upper right */
{ { max_x - sizes[1].w, min_y + sizes[1].h }, { 0, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper left */
{ { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower left */
{ { max_x, min_y }, { 1, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper right */
{ { max_x, max_y }, { 1, 0 }, }, /* Lower right */
{ { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, }, /* Lower left */
{ { max_x, min_y }, { 1, 1 }, }, /* Upper right */
{ { max_x, max_y }, { 1, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower right */
{ { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower left */
{ { max_x, min_y }, { 1, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper right */
},
/* Bottom */
{
{ { min_x + sizes[3].w, max_y - sizes[3].h }, { 0, 1 }, }, /* Upper left */
{ { min_x, max_y }, { 0, 0 }, }, /* Lower left */
{ { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, }, /* Upper right */
{ { min_x + sizes[3].w, max_y - sizes[3].h }, { 0, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper left */
{ { min_x, max_y }, { 0, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower left */
{ { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper right */
{ { max_x, max_y }, { 1, 0 }, }, /* Lower right */
{ { min_x , max_y }, { 0, 0 }, }, /* Lower left */
{ { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, }, /* Upper right */
{ { max_x, max_y }, { 1, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower right */
{ { min_x , max_y }, { 0, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower left */
{ { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper right */
},
/* Left */
{
{ { min_x, min_y }, { 0, 1 }, }, /* Upper left */
{ { min_x, max_y }, { 0, 0 }, }, /* Lower left */
{ { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, }, /* Upper right */
{ { min_x, min_y }, { 0, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper left */
{ { min_x, max_y }, { 0, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower left */
{ { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper right */
{ { min_x + sizes[3].w, max_y - sizes[3].h }, { 1, 0 }, }, /* Lower right */
{ { min_x, max_y }, { 0, 0 }, }, /* Lower left */
{ { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, }, /* Upper right */
{ { min_x + sizes[3].w, max_y - sizes[3].h }, { 1, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower right */
{ { min_x, max_y }, { 0, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower left */
{ { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper right */
}
};
int indices[4] = { 0, 1, 2, 3 };
GskRoundedRect outline;
GskNglProgram *program;
/* We sort them by color */
sort_border_sides (colors, indices);
/* Prepare outline */
gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
@ -1881,16 +1853,12 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob *job,
{
GskNglDrawVertex *vertices;
if (widths[indices[i]] <= 0)
if (widths[i] <= 0)
continue;
gsk_ngl_render_job_begin_draw (job, program);
gsk_ngl_program_set_uniform4fv (job->current_program,
UNIFORM_BORDER_COLOR, 0,
1,
(const float *)&colors[indices[i]]);
vertices = gsk_ngl_command_queue_add_vertices (job->command_queue);
memcpy (vertices, side_data[indices[i]], sizeof (GskNglDrawVertex) * GSK_NGL_N_VERTICES);
memcpy (vertices, side_data[i], sizeof (GskNglDrawVertex) * GSK_NGL_N_VERTICES);
gsk_ngl_render_job_end_draw (job);
}
}
@ -2019,12 +1987,10 @@ gsk_ngl_render_job_visit_unblurred_inset_shadow_node (GskNglRenderJob *job,
gsk_ngl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
gsk_ngl_render_job_set_color (job, gsk_inset_shadow_node_get_color (node));
gsk_ngl_program_set_uniform_rounded_rect (job->current_program,
UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0,
&transformed_outline);
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_INSET_SHADOW_COLOR, 0,
gsk_inset_shadow_node_get_color (node));
gsk_ngl_program_set_uniform1f (job->current_program,
UNIFORM_INSET_SHADOW_SPREAD, 0,
gsk_inset_shadow_node_get_spread (node));
@ -2122,12 +2088,10 @@ gsk_ngl_render_job_visit_blurred_inset_shadow_node (GskNglRenderJob *job,
/* Actual inset shadow outline drawing */
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
gsk_ngl_render_job_set_color (job, gsk_inset_shadow_node_get_color (node));
gsk_ngl_program_set_uniform_rounded_rect (job->current_program,
UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0,
&transformed_outline);
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_INSET_SHADOW_COLOR, 0,
gsk_inset_shadow_node_get_color (node));
gsk_ngl_program_set_uniform1f (job->current_program,
UNIFORM_INSET_SHADOW_SPREAD, 0,
spread * MAX (scale_x, scale_y));
@ -2231,12 +2195,10 @@ gsk_ngl_render_job_visit_unblurred_outset_shadow_node (GskNglRenderJob *job,
gsk_ngl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, unblurred_outset_shadow));
gsk_ngl_render_job_set_color (job, gsk_outset_shadow_node_get_color (node));
gsk_ngl_program_set_uniform_rounded_rect (job->current_program,
UNIFORM_UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, 0,
&transformed_outline);
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_UNBLURRED_OUTSET_SHADOW_COLOR, 0,
gsk_outset_shadow_node_get_color (node));
gsk_ngl_program_set_uniform1f (job->current_program,
UNIFORM_UNBLURRED_OUTSET_SHADOW_SPREAD, 0,
spread);
@ -2387,9 +2349,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job,
/* Draw the outline using color program */
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color));
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_COLOR_COLOR, 0,
&white);
gsk_ngl_render_job_set_color (job, &white);
gsk_ngl_render_job_draw (job, 0, 0, texture_width, texture_height);
gsk_ngl_render_job_end_draw (job);
@ -2433,9 +2393,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job,
init_full_texture_region (&offscreen);
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow));
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_OUTSET_SHADOW_COLOR, 0,
color);
gsk_ngl_render_job_set_color (job, color);
gsk_ngl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D,
@ -2456,9 +2414,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job,
}
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow));
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_OUTSET_SHADOW_COLOR, 0,
color);
gsk_ngl_render_job_set_color (job, color);
gsk_ngl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D,
@ -2747,20 +2703,20 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job,
guint last_texture = 0;
GskNglDrawVertex *vertices;
guint used = 0;
GdkRGBA c;
if (num_glyphs == 0)
return;
/* If the font has color glyphs, we don't need to recolor anything */
if (!force_color && gsk_text_node_has_color_glyphs (node))
{
program = CHOOSE_PROGRAM (job, blit);
}
else
{
program = CHOOSE_PROGRAM (job, coloring);
gsk_ngl_program_set_uniform_color (program, UNIFORM_COLORING_COLOR, 0, color);
}
/* If the font has color glyphs, we don't need to recolor anything.
* We tell the shader by setting the color to vec4(-1).
*/
if (!force_color && gsk_text_node_has_color_glyphs (node))
c = (GdkRGBA) { -1.f, -1.f, -1.f, -1.f };
else
c = *color;
lookup.font = (PangoFont *)font;
lookup.scale = (guint) (text_scale * 1024);
@ -2835,31 +2791,55 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job,
vertices[base+0].position[1] = glyph_y;
vertices[base+0].uv[0] = tx;
vertices[base+0].uv[1] = ty;
vertices[base+0].color[0] = c.red;
vertices[base+0].color[1] = c.green;
vertices[base+0].color[2] = c.blue;
vertices[base+0].color[3] = c.alpha;
vertices[base+1].position[0] = glyph_x;
vertices[base+1].position[1] = glyph_y2;
vertices[base+1].uv[0] = tx;
vertices[base+1].uv[1] = ty2;
vertices[base+1].color[0] = c.red;
vertices[base+1].color[1] = c.green;
vertices[base+1].color[2] = c.blue;
vertices[base+1].color[3] = c.alpha;
vertices[base+2].position[0] = glyph_x2;
vertices[base+2].position[1] = glyph_y;
vertices[base+2].uv[0] = tx2;
vertices[base+2].uv[1] = ty;
vertices[base+2].color[0] = c.red;
vertices[base+2].color[1] = c.green;
vertices[base+2].color[2] = c.blue;
vertices[base+2].color[3] = c.alpha;
vertices[base+3].position[0] = glyph_x2;
vertices[base+3].position[1] = glyph_y2;
vertices[base+3].uv[0] = tx2;
vertices[base+3].uv[1] = ty2;
vertices[base+3].color[0] = c.red;
vertices[base+3].color[1] = c.green;
vertices[base+3].color[2] = c.blue;
vertices[base+3].color[3] = c.alpha;
vertices[base+4].position[0] = glyph_x;
vertices[base+4].position[1] = glyph_y2;
vertices[base+4].uv[0] = tx;
vertices[base+4].uv[1] = ty2;
vertices[base+4].color[0] = c.red;
vertices[base+4].color[1] = c.green;
vertices[base+4].color[2] = c.blue;
vertices[base+4].color[3] = c.alpha;
vertices[base+5].position[0] = glyph_x2;
vertices[base+5].position[1] = glyph_y;
vertices[base+5].uv[0] = tx2;
vertices[base+5].uv[1] = ty;
vertices[base+5].color[0] = c.red;
vertices[base+5].color[1] = c.green;
vertices[base+5].color[2] = c.blue;
vertices[base+5].color[3] = c.alpha;
batch->draw.vbo_count += GSK_NGL_N_VERTICES;
used++;
@ -2952,14 +2932,12 @@ gsk_ngl_render_job_visit_shadow_node (GskNglRenderJob *job,
gsk_ngl_render_job_offset (job, dx, dy);
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring));
gsk_ngl_render_job_set_color (job, &shadow->color);
gsk_ngl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D,
GL_TEXTURE0,
offscreen.texture_id);
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_COLORING_COLOR, 0,
&shadow->color);
gsk_ngl_render_job_load_vertices_from_offscreen (job, &bounds, &offscreen);
gsk_ngl_render_job_end_draw (job);
gsk_ngl_render_job_offset (job, -dx, -dy);
@ -3014,7 +2992,7 @@ gsk_ngl_render_job_visit_blur_node (GskNglRenderJob *job,
GL_TEXTURE_2D,
GL_TEXTURE0,
offscreen.texture_id);
gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y);
gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 1, 1, 0);
gsk_ngl_render_job_end_draw (job);
}
@ -3123,9 +3101,7 @@ gsk_ngl_render_job_visit_gl_shader_node_fallback (GskNglRenderJob *job,
static const GdkRGBA pink = { 255 / 255., 105 / 255., 180 / 255., 1.0 };
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color));
gsk_ngl_program_set_uniform_color (job->current_program,
UNIFORM_COLOR_COLOR, 0,
&pink);
gsk_ngl_render_job_set_color (job, &pink);
gsk_ngl_render_job_draw_rect (job, &node->bounds);
gsk_ngl_render_job_end_draw (job);
}
@ -3317,7 +3293,6 @@ gsk_ngl_render_job_visit_texture_node (GskNglRenderJob *job,
for (guint i = 0; i < n_slices; i ++)
{
GskNglDrawVertex *vertices;
const GskNglTextureSlice *slice = &slices[i];
float x1, x2, y1, y2;
@ -3333,37 +3308,8 @@ gsk_ngl_render_job_visit_texture_node (GskNglRenderJob *job,
GL_TEXTURE_2D,
GL_TEXTURE0,
slice->texture_id);
vertices = gsk_ngl_command_queue_add_vertices (job->command_queue);
vertices[0].position[0] = x1;
vertices[0].position[1] = y1;
vertices[0].uv[0] = 0;
vertices[0].uv[1] = 0;
vertices[1].position[0] = x1;
vertices[1].position[1] = y2;
vertices[1].uv[0] = 0;
vertices[1].uv[1] = 1;
vertices[2].position[0] = x2;
vertices[2].position[1] = y1;
vertices[2].uv[0] = 1;
vertices[2].uv[1] = 0;
vertices[3].position[0] = x2;
vertices[3].position[1] = y2;
vertices[3].uv[0] = 1;
vertices[3].uv[1] = 1;
vertices[4].position[0] = x1;
vertices[4].position[1] = y2;
vertices[4].uv[0] = 0;
vertices[4].uv[1] = 1;
vertices[5].position[0] = x2;
vertices[5].position[1] = y1;
vertices[5].uv[0] = 1;
vertices[5].uv[1] = 0;
gsk_ngl_render_job_draw_coords (job, x1, y1, x2, y2, 0, 0, 1, 1);
}
gsk_ngl_render_job_end_draw (job);
@ -3900,6 +3846,7 @@ gsk_ngl_render_job_new (GskNglDriver *driver,
job->viewport = *viewport;
gsk_ngl_render_job_set_alpha (job, 1.0);
gsk_ngl_render_job_set_color (job, &(GdkRGBA){ 0.f, 0.f, 0.f, 0.f });
gsk_ngl_render_job_set_projection_from_rect (job, viewport, NULL);
gsk_ngl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_factor, scale_factor));

View File

@ -55,6 +55,7 @@ struct _GskNglDrawVertex
{
float position[2];
float uv[2];
float color[4];
};
G_END_DECLS

View File

@ -0,0 +1,314 @@
// VERTEX_SHADER:
// blend.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// blend.glsl
uniform int u_mode;
uniform sampler2D u_source2;
float
combine (float source, float backdrop)
{
return source + backdrop * (1.0 - source);
}
vec4
composite (vec4 Cs, vec4 Cb, vec3 B)
{
float ao = Cs.a + Cb.a * (1.0 - Cs.a);
vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao;
return vec4(Co, ao);
}
vec4
normal (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb);
}
vec4
multiply (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb * Cb.rgb);
}
vec4
difference (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, abs(Cs.rgb - Cb.rgb));
}
vec4
screen (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb + Cb.rgb - Cs.rgb * Cb.rgb);
}
float
hard_light (float source, float backdrop)
{
if (source <= 0.5)
return 2.0 * backdrop * source;
else
return 2.0 * (backdrop + source - backdrop * source) - 1.0;
}
vec4
hard_light (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (hard_light (Cs.r, Cb.r),
hard_light (Cs.g, Cb.g),
hard_light (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
float
soft_light (float source, float backdrop)
{
float db;
if (backdrop <= 0.25)
db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop;
else
db = sqrt (backdrop);
if (source <= 0.5)
return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop);
else
return backdrop + (2.0 * source - 1.0) * (db - backdrop);
}
vec4
soft_light (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (soft_light (Cs.r, Cb.r),
soft_light (Cs.g, Cb.g),
soft_light (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
vec4
overlay (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (hard_light (Cb.r, Cs.r),
hard_light (Cb.g, Cs.g),
hard_light (Cb.b, Cs.b));
return composite (Cs, Cb, B);
}
vec4
darken (vec4 Cs, vec4 Cb)
{
vec3 B = min (Cs.rgb, Cb.rgb);
return composite (Cs, Cb, B);
}
vec4
lighten (vec4 Cs, vec4 Cb)
{
vec3 B = max (Cs.rgb, Cb.rgb);
return composite (Cs, Cb, B);
}
float
color_dodge (float source, float backdrop)
{
return (source == 1.0) ? source : min (backdrop / (1.0 - source), 1.0);
}
vec4
color_dodge (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (color_dodge (Cs.r, Cb.r),
color_dodge (Cs.g, Cb.g),
color_dodge (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
float
color_burn (float source, float backdrop)
{
return (source == 0.0) ? source : max ((1.0 - ((1.0 - backdrop) / source)), 0.0);
}
vec4
color_burn (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (color_burn (Cs.r, Cb.r),
color_burn (Cs.g, Cb.g),
color_burn (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
vec4
exclusion (vec4 Cs, vec4 Cb)
{
vec3 B = Cb.rgb + Cs.rgb - 2.0 * Cb.rgb * Cs.rgb;
return composite (Cs, Cb, B);
}
float
lum (vec3 c)
{
return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
}
vec3
clip_color (vec3 c)
{
float l = lum (c);
float n = min (c.r, min (c.g, c.b));
float x = max (c.r, max (c.g, c.b));
if (n < 0.0) c = l + (((c - l) * l) / (l - n));
if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l));
return c;
}
vec3
set_lum (vec3 c, float l)
{
float d = l - lum (c);
return clip_color (vec3 (c.r + d, c.g + d, c.b + d));
}
float
sat (vec3 c)
{
return max (c.r, max (c.g, c.b)) - min (c.r, min (c.g, c.b));
}
vec3
set_sat (vec3 c, float s)
{
float cmin = min (c.r, min (c.g, c.b));
float cmax = max (c.r, max (c.g, c.b));
vec3 res;
if (cmax == cmin)
res = vec3 (0, 0, 0);
else
{
if (c.r == cmax)
{
if (c.g == cmin)
{
res.b = ((c.b - cmin) * s) / (cmax - cmin);
res.g = 0.0;
}
else
{
res.g = ((c.g - cmin) * s) / (cmax - cmin);
res.b = 0.0;
}
res.r = s;
}
else if (c.g == cmax)
{
if (c.r == cmin)
{
res.b = ((c.b - cmin) * s) / (cmax - cmin);
res.r = 0.0;
}
else
{
res.r = ((c.r - cmin) * s) / (cmax - cmin);
res.b = 0.0;
}
res.g = s;
}
else
{
if (c.r == cmin)
{
res.g = ((c.g - cmin) * s) / (cmax - cmin);
res.r = 0.0;
}
else
{
res.r = ((c.r - cmin) * s) / (cmax - cmin);
res.g = 0.0;
}
res.b = s;
}
}
return res;
}
vec4
color (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (Cs.rgb, lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
hue (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (set_sat (Cs.rgb, sat (Cb.rgb)), lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
saturation (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (set_sat (Cb.rgb, sat (Cs.rgb)), lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
luminosity (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (Cb.rgb, lum (Cs.rgb));
return composite (Cs, Cb, B);
}
void main() {
vec4 bottom_color = GskTexture(u_source, vUv);
vec4 top_color = GskTexture(u_source2, vUv);
vec4 result;
if (u_mode == 0)
result = normal(top_color, bottom_color);
else if (u_mode == 1)
result = multiply(top_color, bottom_color);
else if (u_mode == 2)
result = screen(top_color, bottom_color);
else if (u_mode == 3)
result = overlay(top_color, bottom_color);
else if (u_mode == 4)
result = darken(top_color, bottom_color);
else if (u_mode == 5)
result = lighten(top_color, bottom_color);
else if (u_mode == 6)
result = color_dodge(top_color, bottom_color);
else if (u_mode == 7)
result = color_burn(top_color, bottom_color);
else if (u_mode == 8)
result = hard_light(top_color, bottom_color);
else if (u_mode == 9)
result = soft_light(top_color, bottom_color);
else if (u_mode == 10)
result = difference(top_color, bottom_color);
else if (u_mode == 11)
result = exclusion(top_color, bottom_color);
else if (u_mode == 12)
result = color(top_color, bottom_color);
else if (u_mode == 13)
result = hue(top_color, bottom_color);
else if (u_mode == 14)
result = saturation(top_color, bottom_color);
else if (u_mode == 15)
result = luminosity(top_color, bottom_color);
else
discard;
gskSetOutputColor(result * u_alpha);
}

View File

@ -0,0 +1,17 @@
// VERTEX_SHADER:
// blit.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// blit.glsl
void main() {
vec4 diffuse = GskTexture(u_source, vUv);
gskSetOutputColor(diffuse * u_alpha);
}

View File

@ -0,0 +1,59 @@
// VERTEX_SHADER:
// blur.glsl
uniform float u_blur_radius;
uniform vec2 u_blur_size;
uniform vec2 u_blur_dir;
_OUT_ vec2 pixel_step;
_OUT_ float pixels_per_side;
_OUT_ vec3 initial_gaussian;
const float PI = 3.14159265;
const float RADIUS_MULTIPLIER = 2.0;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
pixel_step = (vec2(1.0) / u_blur_size) * u_blur_dir;
pixels_per_side = floor(u_blur_radius * RADIUS_MULTIPLIER / 2.0);
float sigma = u_blur_radius / 2.0; // *shrug*
initial_gaussian.x = 1.0 / (sqrt(2.0 * PI) * sigma);
initial_gaussian.y = exp(-0.5 / (sigma * sigma));
initial_gaussian.z = initial_gaussian.y * initial_gaussian.y;
}
// FRAGMENT_SHADER:
// blur.glsl
_IN_ vec2 pixel_step;
_IN_ float pixels_per_side;
_IN_ vec3 initial_gaussian;
// blur_radius 0 is NOT supported and MUST be caught before.
// Partially from http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html
void main() {
vec3 incrementalGaussian = initial_gaussian;
float coefficientSum = 0.0;
vec4 sum = GskTexture(u_source, vUv) * incrementalGaussian.x;
coefficientSum += incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
vec2 p = pixel_step;
for (int i = 1; i <= int(pixels_per_side); i++) {
sum += GskTexture(u_source, vUv - p) * incrementalGaussian.x;
sum += GskTexture(u_source, vUv + p) * incrementalGaussian.x;
coefficientSum += 2.0 * incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
p += pixel_step;
}
gskSetOutputColor(sum / coefficientSum);
}

View File

@ -0,0 +1,43 @@
// VERTEX_SHADER:
// border.glsl
uniform vec4 u_widths;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
final_color = gsk_premultiply(aColor) * u_alpha;
GskRoundedRect outside = gsk_create_rect(u_outline_rect);
GskRoundedRect inside = gsk_rounded_rect_shrink (outside, u_widths);
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
// border.glsl
uniform vec4[3] u_outline_rect;
_IN_ vec4 final_color;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
gskSetOutputColor(final_color * alpha);
}

View File

@ -0,0 +1,20 @@
// VERTEX_SHADER:
// color.glsl
_OUT_ vec4 final_color;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
final_color = gsk_premultiply(aColor) * u_alpha;
}
// FRAGMENT_SHADER:
// color.glsl
_IN_ vec4 final_color;
void main() {
gskSetOutputColor(final_color);
}

View File

@ -0,0 +1,29 @@
// VERTEX_SHADER:
// color_matrix.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// color_matrix.glsl
uniform mat4 u_color_matrix;
uniform vec4 u_color_offset;
void main() {
vec4 color = GskTexture(u_source, vUv);
// Un-premultilpy
if (color.a != 0.0)
color.rgb /= color.a;
color = u_color_matrix * color + u_color_offset;
color = clamp(color, 0.0, 1.0);
color.rgb *= color.a;
gskSetOutputColor(color * u_alpha);
}

View File

@ -0,0 +1,36 @@
// VERTEX_SHADER:
// coloring.glsl
_OUT_ vec4 final_color;
flat _OUT_ int use_color;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
// We use this shader for both plain glyphs (used as mask)
// and color glpyhs (used as source). The renderer sets
// aColor to vec4(-1) for color glyhs.
if (distance(aColor, vec4(-1)) < 0.001)
use_color = 0;
else
use_color = 1;
final_color = gsk_premultiply(aColor) * u_alpha;
}
// FRAGMENT_SHADER:
// coloring.glsl
_IN_ vec4 final_color;
flat _IN_ int use_color;
void main() {
vec4 diffuse = GskTexture(u_source, vUv);
if (use_color == 1)
gskSetOutputColor(final_color * diffuse.a);
else
gskSetOutputColor(diffuse * u_alpha);
}

View File

@ -0,0 +1,76 @@
// VERTEX_SHADER
// conic_gradient.glsl
uniform vec4 u_geometry;
_NOPERSPECTIVE_ _OUT_ vec2 coord;
void main() {
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_geometry.xy;
coord = vec2(dot(mv0, offset), dot(mv1, offset));
}
// FRAGMENT_SHADER:
// conic_gradient.glsl
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops; // Why? Because it works like this.
#endif
uniform vec4 u_geometry;
uniform float u_color_stops[6 * 5];
_NOPERSPECTIVE_ _IN_ vec2 coord;
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
// direction of point in range [-PI, PI]
vec2 pos = floor(coord);
float angle = atan(pos.y, pos.x);
// fract() does the modulo here, so now we have progress
// into the current conic
float offset = fract(angle * u_geometry.z + u_geometry.w);
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}

View File

@ -0,0 +1,24 @@
// VERTEX_SHADER:
// cross_fade.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// cross_fade.glsl
uniform float u_progress;
uniform sampler2D u_source2;
void main() {
vec4 source1 = GskTexture(u_source, vUv); // start child
vec4 source2 = GskTexture(u_source2, vUv); // end child
float p_start = (1.0 - u_progress) * u_alpha;
float p_end = u_progress * u_alpha;
vec4 color = (p_start * source1) + (p_end * source2);
gskSetOutputColor(color);
}

View File

@ -0,0 +1,25 @@
// VERTEX_SHADER:
// custom.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// custom.glsl
// The shader supplies:
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv);
uniform vec2 u_size;
uniform sampler2D u_source2;
uniform sampler2D u_source3;
uniform sampler2D u_source4;
void main() {
vec4 fragColor;
vec2 fragCoord = vec2(vUv.x * u_size.x, (1.0-vUv.y) * u_size.y);
mainImage(fragColor, fragCoord, u_size, vUv);
gskSetOutputColor(fragColor);
}

View File

@ -0,0 +1,44 @@
// VERTEX_SHADER:
// inset_shadow.glsl
uniform float u_spread;
uniform vec2 u_offset;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
final_color = gsk_premultiply(aColor) * u_alpha;
GskRoundedRect outside = gsk_create_rect(u_outline_rect);
GskRoundedRect inside = gsk_rounded_rect_shrink(outside, vec4(u_spread));
gsk_rounded_rect_offset(inside, u_offset);
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
// inset_shadow.glsl
_IN_ vec4 final_color;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
gskSetOutputColor(final_color * alpha);
}

View File

@ -0,0 +1,98 @@
// VERTEX_SHADER
// linear_gradient.glsl
uniform vec4 u_points;
_NOPERSPECTIVE_ _OUT_ vec4 info;
void main() {
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_points.xy;
vec2 coord = vec2(dot(mv0, offset),
dot(mv1, offset));
// Original equation:
// VS | maxDist = length(end - start);
// VS | gradient = end - start;
// VS | gradientLength = length(gradient);
// FS | pos = frag_coord - start
// FS | proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient
// FS | offset = length(proj) / maxDist
// Simplified formula derivation:
// 1. Notice that maxDist = gradientLength:
// offset = length(proj) / gradientLength
// 2. Let gnorm = gradient / gradientLength, then:
// proj = (dot(gnorm * gradientLength, pos) / (gradientLength * gradientLength)) * (gnorm * gradientLength) =
// = dot(gnorm, pos) * gnorm
// 3. Since gnorm is unit length then:
// length(proj) = length(dot(gnorm, pos) * gnorm) = dot(gnorm, pos)
// 4. We can avoid the FS division by passing a scaled pos from the VS:
// offset = dot(gnorm, pos) / gradientLength = dot(gnorm, pos / gradientLength)
// 5. 1.0 / length(gradient) is inversesqrt(dot(gradient, gradient)) in GLSL
vec2 gradient = vec2(dot(mv0, u_points.zw),
dot(mv1, u_points.zw));
float rcp_gradient_length = inversesqrt(dot(gradient, gradient));
info = rcp_gradient_length * vec4(coord, gradient);
}
// FRAGMENT_SHADER:
// linear_gradient.glsl
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops; // Why? Because it works like this.
#endif
uniform float u_color_stops[6 * 5];
uniform bool u_repeat;
_NOPERSPECTIVE_ _IN_ vec4 info;
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
float offset = dot(info.xy, info.zw);
if (u_repeat) {
offset = fract(offset);
}
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}

View File

@ -0,0 +1,36 @@
// VERTEX_SHADER:
// outset_shadow.glsl
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
final_color = gsk_premultiply(aColor) * u_alpha;
GskRoundedRect outline = gsk_create_rect(u_outline_rect);
gsk_rounded_rect_transform(outline, u_modelview);
gsk_rounded_rect_encode(outline, transformed_outline);
}
// FRAGMENT_SHADER:
// outset_shadow.glsl
_IN_ vec4 final_color;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float alpha = GskTexture(u_source, vUv).a;
alpha *= (1.0 - clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outline), frag), 0.0, 1.0));
vec4 color = final_color * alpha;
gskSetOutputColor(color);
}

View File

@ -0,0 +1,138 @@
uniform sampler2D u_source;
uniform mat4 u_projection;
uniform mat4 u_modelview;
uniform float u_alpha;
uniform vec4 u_viewport;
uniform vec4[3] u_clip_rect;
#if defined(GSK_LEGACY)
_OUT_ vec4 outputColor;
#elif !defined(GSK_GLES)
_OUT_ vec4 outputColor;
#endif
_IN_ vec2 vUv;
GskRoundedRect gsk_decode_rect(_GSK_ROUNDED_RECT_UNIFORM_ r)
{
#if defined(GSK_GLES) || defined(GSK_LEGACY)
return GskRoundedRect(r[0], r[1], r[2]);
#else
return r;
#endif
}
float
gsk_ellipsis_dist (vec2 p, vec2 radius)
{
if (radius == vec2(0, 0))
return 0.0;
vec2 p0 = p / radius;
vec2 p1 = 2.0 * p0 / radius;
return (dot(p0, p0) - 1.0) / length (p1);
}
float
gsk_ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
{
float d = gsk_ellipsis_dist (point - center, radius);
return clamp (0.5 - d, 0.0, 1.0);
}
float
gsk_rounded_rect_coverage (GskRoundedRect r, vec2 p)
{
if (p.x < r.bounds.x || p.y < r.bounds.y ||
p.x >= r.bounds.z || p.y >= r.bounds.w)
return 0.0;
vec2 ref_tl = r.corner_points1.xy;
vec2 ref_tr = r.corner_points1.zw;
vec2 ref_br = r.corner_points2.xy;
vec2 ref_bl = r.corner_points2.zw;
if (p.x >= ref_tl.x && p.x >= ref_bl.x &&
p.x <= ref_tr.x && p.x <= ref_br.x)
return 1.0;
if (p.y >= ref_tl.y && p.y >= ref_tr.y &&
p.y <= ref_bl.y && p.y <= ref_br.y)
return 1.0;
vec2 rad_tl = r.corner_points1.xy - r.bounds.xy;
vec2 rad_tr = r.corner_points1.zw - r.bounds.zy;
vec2 rad_br = r.corner_points2.xy - r.bounds.zw;
vec2 rad_bl = r.corner_points2.zw - r.bounds.xw;
float d_tl = gsk_ellipsis_coverage(p, ref_tl, rad_tl);
float d_tr = gsk_ellipsis_coverage(p, ref_tr, rad_tr);
float d_br = gsk_ellipsis_coverage(p, ref_br, rad_br);
float d_bl = gsk_ellipsis_coverage(p, ref_bl, rad_bl);
vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
p.x > ref_tr.x && p.y < ref_tr.y,
p.x > ref_br.x && p.y > ref_br.y,
p.x < ref_bl.x && p.y > ref_bl.y);
return 1.0 - dot(vec4(is_out), corner_coverages);
}
float
gsk_rect_coverage (vec4 r, vec2 p)
{
if (p.x < r.x || p.y < r.y ||
p.x >= r.z || p.y >= r.w)
return 0.0;
return 1.0;
}
vec4 GskTexture(sampler2D sampler, vec2 texCoords) {
#if defined(GSK_GLES) || defined(GSK_LEGACY)
return texture2D(sampler, texCoords);
#else
return texture(sampler, texCoords);
#endif
}
#ifdef GSK_GL3
layout(origin_upper_left) in vec4 gl_FragCoord;
#endif
vec2 gsk_get_frag_coord() {
vec2 fc = gl_FragCoord.xy;
#ifdef GSK_GL3
fc += u_viewport.xy;
#else
fc.x += u_viewport.x;
fc.y = (u_viewport.y + u_viewport.w) - fc.y;
#endif
return fc;
}
void gskSetOutputColor(vec4 color) {
vec4 result;
#if defined(NO_CLIP)
result = color;
#elif defined(RECT_CLIP)
result = color * gsk_rect_coverage(gsk_get_bounds(u_clip_rect),
gsk_get_frag_coord());
#else
result = color * gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect),
gsk_get_frag_coord());
#endif
#if defined(GSK_GLES) || defined(GSK_LEGACY)
gl_FragColor = result;
#else
outputColor = result;
#endif
}

View File

@ -0,0 +1,57 @@
#ifndef GSK_LEGACY
precision highp float;
#endif
#if defined(GSK_GLES) || defined(GSK_LEGACY)
#define _OUT_ varying
#define _IN_ varying
#define _NOPERSPECTIVE_
#define _GSK_ROUNDED_RECT_UNIFORM_ vec4[3]
#else
#define _OUT_ out
#define _IN_ in
#define _NOPERSPECTIVE_ noperspective
#define _GSK_ROUNDED_RECT_UNIFORM_ GskRoundedRect
#endif
struct GskRoundedRect
{
vec4 bounds; // Top left and bottom right
// Look, arrays can't be in structs if you want to return the struct
// from a function in gles or whatever. Just kill me.
vec4 corner_points1; // xy = top left, zw = top right
vec4 corner_points2; // xy = bottom right, zw = bottom left
};
// Transform from a C GskRoundedRect to what we need.
GskRoundedRect
gsk_create_rect(vec4[3] data)
{
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
vec4 corner_points1 = vec4(bounds.xy + data[1].xy,
bounds.zy + vec2(data[1].zw * vec2(-1, 1)));
vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
bounds.xw + vec2(data[2].zw * vec2(1, -1)));
return GskRoundedRect(bounds, corner_points1, corner_points2);
}
vec4
gsk_get_bounds(vec4[3] data)
{
return vec4(data[0].xy, data[0].xy + data[0].zw);
}
vec4 gsk_premultiply(vec4 c) {
return vec4(c.rgb * c.a, c.a);
}
vec4 gsk_scaled_premultiply(vec4 c, float s) {
// Fast version of gsk_premultiply(c) * s
// 4 muls instead of 7
float a = s * c.a;
return vec4(c.rgb * a, a);
}

View File

@ -0,0 +1,71 @@
uniform mat4 u_projection;
uniform mat4 u_modelview;
uniform float u_alpha;
#if defined(GSK_GLES) || defined(GSK_LEGACY)
attribute vec2 aPosition;
attribute vec2 aUv;
attribute vec4 aColor;
_OUT_ vec2 vUv;
#else
_IN_ vec2 aPosition;
_IN_ vec2 aUv;
_IN_ vec4 aColor;
_OUT_ vec2 vUv;
#endif
// amount is: top, right, bottom, left
GskRoundedRect
gsk_rounded_rect_shrink (GskRoundedRect r, vec4 amount)
{
vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
vec4 new_corner_points1 = r.corner_points1;
vec4 new_corner_points2 = r.corner_points2;
if (r.corner_points1.xy == r.bounds.xy) new_corner_points1.xy = new_bounds.xy;
if (r.corner_points1.zw == r.bounds.zy) new_corner_points1.zw = new_bounds.zy;
if (r.corner_points2.xy == r.bounds.zw) new_corner_points2.xy = new_bounds.zw;
if (r.corner_points2.zw == r.bounds.xw) new_corner_points2.zw = new_bounds.xw;
return GskRoundedRect (new_bounds, new_corner_points1, new_corner_points2);
}
void
gsk_rounded_rect_offset(inout GskRoundedRect r, vec2 offset)
{
r.bounds.xy += offset;
r.bounds.zw += offset;
r.corner_points1.xy += offset;
r.corner_points1.zw += offset;
r.corner_points2.xy += offset;
r.corner_points2.zw += offset;
}
void gsk_rounded_rect_transform(inout GskRoundedRect r, mat4 mat)
{
r.bounds.xy = (mat * vec4(r.bounds.xy, 0.0, 1.0)).xy;
r.bounds.zw = (mat * vec4(r.bounds.zw, 0.0, 1.0)).xy;
r.corner_points1.xy = (mat * vec4(r.corner_points1.xy, 0.0, 1.0)).xy;
r.corner_points1.zw = (mat * vec4(r.corner_points1.zw, 0.0, 1.0)).xy;
r.corner_points2.xy = (mat * vec4(r.corner_points2.xy, 0.0, 1.0)).xy;
r.corner_points2.zw = (mat * vec4(r.corner_points2.zw, 0.0, 1.0)).xy;
}
#if defined(GSK_LEGACY)
// Can't have out or inout array parameters...
#define gsk_rounded_rect_encode(r, uni) uni[0] = r.bounds; uni[1] = r.corner_points1; uni[2] = r.corner_points2;
#else
void gsk_rounded_rect_encode(GskRoundedRect r, out _GSK_ROUNDED_RECT_UNIFORM_ out_r)
{
#if defined(GSK_GLES)
out_r[0] = r.bounds;
out_r[1] = r.corner_points1;
out_r[2] = r.corner_points2;
#else
out_r = r;
#endif
}
#endif

View File

@ -0,0 +1,78 @@
// VERTEX_SHADER
// radial_gradient.glsl
uniform vec4 u_geometry;
_NOPERSPECTIVE_ _OUT_ vec2 coord;
void main() {
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_geometry.xy;
vec2 dir = vec2(dot(mv0, offset),
dot(mv1, offset));
coord = dir * u_geometry.zw;
}
// FRAGMENT_SHADER:
// radial_gradient.glsl
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops;
#endif
uniform bool u_repeat;
uniform vec2 u_range;
uniform float u_color_stops[6 * 5];
_NOPERSPECTIVE_ _IN_ vec2 coord;
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
// Reverse scale
float offset = length(coord) * u_range.x + u_range.y;
if (u_repeat) {
offset = fract(offset);
}
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}

View File

@ -0,0 +1,44 @@
// VERTEX_SHADER:
// repeat.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// repeat.glsl
uniform vec4 u_child_bounds;
uniform vec4 u_texture_rect;
float wrap(float f, float wrap_for) {
return mod(f, wrap_for);
}
/* We get the texture coordinates via vUv,
* but that might be on a texture atlas, so we need to do the
* wrapping ourselves.
*/
void main() {
/* We map the texture coordinate to [1;0], then wrap it and scale the result again */
float tw = u_texture_rect.z - u_texture_rect.x;
float th = u_texture_rect.w - u_texture_rect.y;
float mapped_x = (vUv.x - u_texture_rect.x) / tw;
float mapped_y = (vUv.y - u_texture_rect.y) / th;
float wrapped_x = wrap(u_child_bounds.x + mapped_x * u_child_bounds.z, 1.0);
float wrapped_y = wrap(u_child_bounds.y + mapped_y * u_child_bounds.w, 1.0);
vec2 tp;
tp.x = u_texture_rect.x + (wrapped_x * tw);
tp.y = u_texture_rect.y + (wrapped_y * th);
vec4 diffuse = GskTexture(u_source, tp);
gskSetOutputColor(diffuse * u_alpha);
}

View File

@ -0,0 +1,44 @@
// VERTEX_SHADER:
// unblurred_outset_shadow.glsl
uniform float u_spread;
uniform vec2 u_offset;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
final_color = gsk_premultiply(aColor) * u_alpha;
GskRoundedRect inside = gsk_create_rect(u_outline_rect);
GskRoundedRect outside = gsk_rounded_rect_shrink(inside, vec4(- u_spread));
gsk_rounded_rect_offset(outside, u_offset);
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
// unblurred_outset_shadow.glsl
_IN_ vec4 final_color;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
gskSetOutputColor(final_color * alpha);
}