Compare commits
4 Commits
main
...
ngl-tweaks
Author | SHA1 | Date | |
---|---|---|---|
|
b9d21f1f1a | ||
|
8baf29063c | ||
|
70bf1ed0e4 | ||
|
a041c18676 |
@@ -7,6 +7,7 @@ gsk_private_gl_shaders = [
|
||||
'resources/glsl/coloring.glsl',
|
||||
'resources/glsl/color.glsl',
|
||||
'resources/glsl/linear_gradient.glsl',
|
||||
'resources/glsl/linear_gradient_2.glsl',
|
||||
'resources/glsl/radial_gradient.glsl',
|
||||
'resources/glsl/conic_gradient.glsl',
|
||||
'resources/glsl/color_matrix.glsl',
|
||||
|
@@ -57,6 +57,12 @@ GSK_NGL_DEFINE_PROGRAM (linear_gradient,
|
||||
GSK_NGL_ADD_UNIFORM (3, LINEAR_GRADIENT_POINTS, u_points)
|
||||
GSK_NGL_ADD_UNIFORM (4, LINEAR_GRADIENT_REPEAT, u_repeat))
|
||||
|
||||
GSK_NGL_DEFINE_PROGRAM (linear_gradient_2,
|
||||
"/org/gtk/libgsk/glsl/linear_gradient_2.glsl",
|
||||
GSK_NGL_ADD_UNIFORM (1, LINEAR_GRADIENT_2_COLOR_STOPS, u_color_stops)
|
||||
GSK_NGL_ADD_UNIFORM (2, LINEAR_GRADIENT_2_POINTS, u_points)
|
||||
GSK_NGL_ADD_UNIFORM (3, LINEAR_GRADIENT_2_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)
|
||||
|
@@ -286,6 +286,8 @@ gsk_ngl_renderer_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (gsk_ngl_renderer_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
extern void dump_program_counters (void);
|
||||
|
||||
static void
|
||||
gsk_ngl_renderer_class_init (GskNglRendererClass *klass)
|
||||
{
|
||||
@@ -298,6 +300,8 @@ gsk_ngl_renderer_class_init (GskNglRendererClass *klass)
|
||||
renderer_class->unrealize = gsk_ngl_renderer_unrealize;
|
||||
renderer_class->render = gsk_ngl_renderer_render;
|
||||
renderer_class->render_texture = gsk_ngl_renderer_render_texture;
|
||||
|
||||
g_atexit (dump_program_counters);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -874,6 +874,9 @@ gsk_ngl_render_job_update_clip (GskNglRenderJob *job,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void update_program_counters (GskNglRenderJob *job,
|
||||
float width, float height);
|
||||
|
||||
/* load_vertex_data_with_region */
|
||||
static inline void
|
||||
gsk_ngl_render_job_load_vertices_from_offscreen (GskNglRenderJob *job,
|
||||
@@ -888,6 +891,8 @@ 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;
|
||||
|
||||
update_program_counters (job, max_x - min_x, max_y - min_y);
|
||||
|
||||
vertices[0].position[0] = min_x;
|
||||
vertices[0].position[1] = min_y;
|
||||
vertices[0].uv[0] = offscreen->area.x;
|
||||
@@ -933,6 +938,8 @@ gsk_ngl_render_job_draw (GskNglRenderJob *job,
|
||||
float max_x = min_x + width;
|
||||
float max_y = min_y + height;
|
||||
|
||||
update_program_counters (job, width, height);
|
||||
|
||||
vertices[0].position[0] = min_x;
|
||||
vertices[0].position[1] = min_y;
|
||||
vertices[0].uv[0] = 0;
|
||||
@@ -986,6 +993,8 @@ gsk_ngl_render_job_draw_coords (GskNglRenderJob *job,
|
||||
{
|
||||
GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue);
|
||||
|
||||
update_program_counters (job, max_x - min_x, max_y - min_y);
|
||||
|
||||
vertices[0].position[0] = min_x;
|
||||
vertices[0].position[1] = min_y;
|
||||
vertices[0].uv[0] = 0;
|
||||
@@ -1030,6 +1039,68 @@ gsk_ngl_render_job_draw_offscreen_rect (GskNglRenderJob *job,
|
||||
gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
#define GSK_NGL_NO_UNIFORMS
|
||||
#define GSK_NGL_ADD_UNIFORM(pos, KEY, name)
|
||||
#define GSK_NGL_DEFINE_PROGRAM(name, resource, uniforms) \
|
||||
guint64 name ## _no_clip; \
|
||||
guint64 name ## _rect_clip; \
|
||||
guint64 name;
|
||||
# include "gsknglprograms.defs"
|
||||
#undef GSK_NGL_NO_UNIFORMS
|
||||
#undef GSK_NGL_ADD_UNIFORM
|
||||
#undef GSK_NGL_DEFINE_PROGRAM
|
||||
} ProgramCounters;
|
||||
|
||||
static ProgramCounters counters;
|
||||
|
||||
void dump_program_counters (void);
|
||||
|
||||
void
|
||||
dump_program_counters (void)
|
||||
{
|
||||
#define GSK_NGL_NO_UNIFORMS
|
||||
#define GSK_NGL_ADD_UNIFORM(pos, KEY, name)
|
||||
#define PRINT_ONE(name) \
|
||||
g_print ("%lu " #name "\n", counters.name);
|
||||
#define GSK_NGL_DEFINE_PROGRAM(name, resource, uniforms) \
|
||||
PRINT_ONE(name ## _no_clip) \
|
||||
PRINT_ONE(name ## _rect_clip) \
|
||||
PRINT_ONE(name)
|
||||
# include "gsknglprograms.defs"
|
||||
#undef GSK_NGL_NO_UNIFORMS
|
||||
#undef GSK_NGL_ADD_UNIFORM
|
||||
#undef GSK_NGL_DEFINE_PROGRAM
|
||||
}
|
||||
|
||||
static void
|
||||
update_prog_counters (GskNglRenderJob *job,
|
||||
GskNglProgram *program,
|
||||
float width, float height)
|
||||
{
|
||||
guint64 pixels = ceilf (width) * ceilf (height);
|
||||
#define GSK_NGL_NO_UNIFORMS
|
||||
#define GSK_NGL_ADD_UNIFORM(pos, KEY, name)
|
||||
#define GSK_NGL_DEFINE_PROGRAM(name, resource, uniforms) \
|
||||
if (program == job->driver->name) \
|
||||
counters.name += pixels; \
|
||||
else if (program == job->driver->name ## _no_clip) \
|
||||
counters.name ## _no_clip += pixels; \
|
||||
else if (program == job->driver->name ## _rect_clip) \
|
||||
counters.name ## _rect_clip += pixels;
|
||||
# include "gsknglprograms.defs"
|
||||
#undef GSK_NGL_NO_UNIFORMS
|
||||
#undef GSK_NGL_ADD_UNIFORM
|
||||
#undef GSK_NGL_DEFINE_PROGRAM
|
||||
}
|
||||
|
||||
static void
|
||||
update_program_counters (GskNglRenderJob *job,
|
||||
float width, float height)
|
||||
{
|
||||
update_prog_counters (job, job->current_program, width, height);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_ngl_render_job_begin_draw (GskNglRenderJob *job,
|
||||
GskNglProgram *program)
|
||||
@@ -1422,6 +1493,37 @@ gsk_ngl_render_job_visit_linear_gradient_node (GskNglRenderJob *job,
|
||||
gsk_ngl_render_job_end_draw (job);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_ngl_render_job_visit_linear_gradient_2_node (GskNglRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
{
|
||||
const GskColorStop *stops = gsk_linear_gradient_node_get_color_stops (node, NULL);
|
||||
const graphene_point_t *start = gsk_linear_gradient_node_get_start (node);
|
||||
const graphene_point_t *end = gsk_linear_gradient_node_get_end (node);
|
||||
int n_color_stops = gsk_linear_gradient_node_get_n_color_stops (node);
|
||||
gboolean repeat = gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE;
|
||||
float x1 = job->offset_x + start->x;
|
||||
float x2 = job->offset_x + end->x;
|
||||
float y1 = job->offset_y + start->y;
|
||||
float y2 = job->offset_y + end->y;
|
||||
|
||||
g_assert (n_color_stops == 2);
|
||||
|
||||
gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, linear_gradient_2));
|
||||
gsk_ngl_program_set_uniform1fv (job->current_program,
|
||||
UNIFORM_LINEAR_GRADIENT_2_COLOR_STOPS, 0,
|
||||
n_color_stops * 5,
|
||||
(const float *)stops);
|
||||
gsk_ngl_program_set_uniform4f (job->current_program,
|
||||
UNIFORM_LINEAR_GRADIENT_2_POINTS, 0,
|
||||
x1, y1, x2 - x1, y2 - y1);
|
||||
gsk_ngl_program_set_uniform1i (job->current_program,
|
||||
UNIFORM_LINEAR_GRADIENT_2_REPEAT, 0,
|
||||
repeat);
|
||||
gsk_ngl_render_job_draw_rect (job, &node->bounds);
|
||||
gsk_ngl_render_job_end_draw (job);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_ngl_render_job_visit_conic_gradient_node (GskNglRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
@@ -1564,6 +1666,84 @@ gsk_ngl_render_job_visit_clip_node (GskNglRenderJob *job,
|
||||
gsk_ngl_render_job_visit_clipped_child (job, child, clip);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_ngl_render_job_visit_rounded_color_node (GskNglRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
{
|
||||
const GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
|
||||
const GskRoundedRect *clip = gsk_rounded_clip_node_get_clip (node);
|
||||
const graphene_rect_t *outer;
|
||||
graphene_rect_t inner;
|
||||
graphene_rect_t rect;
|
||||
|
||||
outer = &node->bounds;
|
||||
rounded_rect_get_inner (clip, &inner);
|
||||
graphene_rect_intersection (outer, &inner, &inner);
|
||||
|
||||
gsk_ngl_render_job_begin_draw (job, job->driver->color);
|
||||
gsk_ngl_program_set_uniform_color (job->current_program,
|
||||
UNIFORM_COLOR_COLOR, 0,
|
||||
gsk_color_node_get_color (child));
|
||||
|
||||
/* top left */
|
||||
rect.origin.x = outer->origin.x;
|
||||
rect.origin.y = outer->origin.y;
|
||||
rect.size.width = inner.origin.x - rect.origin.x;
|
||||
rect.size.height = inner.origin.y - rect.origin.y;
|
||||
gsk_ngl_render_job_draw_rect (job, &rect);
|
||||
|
||||
/* top right */
|
||||
rect.origin.x = inner.origin.x + inner.size.width;
|
||||
rect.origin.y = outer->origin.y;
|
||||
rect.size.width = outer->origin.x + outer->size.width - rect.origin.x;
|
||||
rect.size.height = inner.origin.y - rect.origin.y;
|
||||
gsk_ngl_render_job_draw_rect (job, &rect);
|
||||
|
||||
/* bottom right */
|
||||
rect.origin.x = inner.origin.x + inner.size.width;
|
||||
rect.origin.y = inner.origin.y + inner.size.height;
|
||||
rect.size.width = outer->origin.x + outer->size.width - rect.origin.x;
|
||||
rect.size.height = outer->origin.y + outer->size.height - rect.origin.y;
|
||||
gsk_ngl_render_job_draw_rect (job, &rect);
|
||||
|
||||
/* bottom left */
|
||||
rect.origin.x = outer->origin.x;
|
||||
rect.origin.y = inner.origin.y + inner.size.height;
|
||||
rect.size.width = inner.origin.x - rect.origin.x;
|
||||
rect.size.height = outer->origin.y + outer->size.height - rect.origin.y;
|
||||
gsk_ngl_render_job_draw_rect (job, &rect);
|
||||
|
||||
gsk_ngl_render_job_end_draw (job);
|
||||
|
||||
gsk_ngl_render_job_begin_draw (job, job->driver->color_no_clip);
|
||||
gsk_ngl_program_set_uniform_color (job->current_program,
|
||||
UNIFORM_COLOR_COLOR, 0,
|
||||
gsk_color_node_get_color (child));
|
||||
|
||||
/* left side */
|
||||
rect.origin.x = outer->origin.x;
|
||||
rect.origin.y = inner.origin.y;
|
||||
rect.size.width = inner.origin.x - rect.origin.x;
|
||||
rect.size.height = inner.size.height;
|
||||
gsk_ngl_render_job_draw_rect (job, &rect);
|
||||
|
||||
/* center */
|
||||
rect.origin.x = inner.origin.x;
|
||||
rect.origin.y = outer->origin.y;
|
||||
rect.size.width = inner.size.width;
|
||||
rect.size.height = outer->size.height;
|
||||
gsk_ngl_render_job_draw_rect (job, &rect);
|
||||
|
||||
/* right side */
|
||||
rect.origin.x = inner.origin.x + inner.size.width;
|
||||
rect.origin.y = inner.origin.y;
|
||||
rect.size.width = outer->origin.x + outer->size.width - rect.origin.x;
|
||||
rect.size.height = inner.size.height;
|
||||
gsk_ngl_render_job_draw_rect (job, &rect);
|
||||
|
||||
gsk_ngl_render_job_end_draw (job);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_ngl_render_job_visit_rounded_clip_node (GskNglRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
@@ -1586,6 +1766,16 @@ gsk_ngl_render_job_visit_rounded_clip_node (GskNglRenderJob *job,
|
||||
transformed_clip.corner[i].height = clip->corner[i].height * scale_y;
|
||||
}
|
||||
|
||||
if (gsk_render_node_get_node_type (child) == GSK_COLOR_NODE &&
|
||||
job->current_clip->is_fully_contained)
|
||||
{
|
||||
/* special-case CSS backgrounds */
|
||||
gsk_ngl_render_job_push_clip (job, &transformed_clip);
|
||||
gsk_ngl_render_job_visit_rounded_color_node (job, node);
|
||||
gsk_ngl_render_job_pop_clip (job);
|
||||
return;
|
||||
}
|
||||
|
||||
if (job->current_clip->is_rectilinear)
|
||||
{
|
||||
GskRoundedRect intersected_clip;
|
||||
@@ -1869,6 +2059,11 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob *job,
|
||||
|
||||
program = CHOOSE_PROGRAM (job, border);
|
||||
|
||||
update_prog_counters (job, program, max_x - min_x, widths[0]);
|
||||
update_prog_counters (job, program, max_y - min_y, widths[1]);
|
||||
update_prog_counters (job, program, max_x - min_x, widths[2]);
|
||||
update_prog_counters (job, program, max_y - min_y, widths[3]);
|
||||
|
||||
gsk_ngl_program_set_uniform4fv (program,
|
||||
UNIFORM_BORDER_WIDTHS, 0,
|
||||
1,
|
||||
@@ -2831,6 +3026,8 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job,
|
||||
glyph_x2 = glyph_x + glyph->ink_rect.width;
|
||||
glyph_y2 = glyph_y + glyph->ink_rect.height;
|
||||
|
||||
update_program_counters (job, glyph->ink_rect.width, glyph->ink_rect.height);
|
||||
|
||||
vertices[base+0].position[0] = glyph_x;
|
||||
vertices[base+0].position[1] = glyph_y;
|
||||
vertices[base+0].uv[0] = tx;
|
||||
@@ -3529,7 +3726,9 @@ gsk_ngl_render_job_visit_node (GskNglRenderJob *job,
|
||||
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
if (gsk_linear_gradient_node_get_n_color_stops (node) < MAX_GRADIENT_STOPS)
|
||||
if (gsk_linear_gradient_node_get_n_color_stops (node) == 2)
|
||||
gsk_ngl_render_job_visit_linear_gradient_2_node (job, node);
|
||||
else if (gsk_linear_gradient_node_get_n_color_stops (node) < MAX_GRADIENT_STOPS)
|
||||
gsk_ngl_render_job_visit_linear_gradient_node (job, node);
|
||||
else
|
||||
gsk_ngl_render_job_visit_as_fallback (job, node);
|
||||
@@ -3540,10 +3739,26 @@ gsk_ngl_render_job_visit_node (GskNglRenderJob *job,
|
||||
break;
|
||||
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
if (gsk_outset_shadow_node_get_blur_radius (node) > 0)
|
||||
gsk_ngl_render_job_visit_blurred_outset_shadow_node (job, node);
|
||||
else
|
||||
gsk_ngl_render_job_visit_unblurred_outset_shadow_node (job, node);
|
||||
{
|
||||
const GskRoundedRect *outline = gsk_outset_shadow_node_get_outline (node);
|
||||
GskRoundedRect transformed_outline;
|
||||
|
||||
gsk_ngl_render_job_transform_bounds (job, &outline->bounds, &transformed_outline.bounds);
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (transformed_outline.corner); i++)
|
||||
{
|
||||
transformed_outline.corner[i].width = outline->corner[i].width * job->scale_x;
|
||||
transformed_outline.corner[i].height = outline->corner[i].height * job->scale_y;
|
||||
}
|
||||
|
||||
if (!gsk_rounded_rect_contains_rect (&transformed_outline, &job->current_clip->rect.bounds))
|
||||
{
|
||||
if (gsk_outset_shadow_node_get_blur_radius (node) > 0)
|
||||
gsk_ngl_render_job_visit_blurred_outset_shadow_node (job, node);
|
||||
else
|
||||
gsk_ngl_render_job_visit_unblurred_outset_shadow_node (job, node);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
|
84
gsk/resources/glsl/linear_gradient_2.glsl
Normal file
84
gsk/resources/glsl/linear_gradient_2.glsl
Normal file
@@ -0,0 +1,84 @@
|
||||
// VERTEX_SHADER
|
||||
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:
|
||||
uniform float u_color_stops[2 * 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);
|
||||
}
|
||||
|
||||
float offset0 = get_offset(0);
|
||||
float offset1 = get_offset(1);
|
||||
|
||||
if (offset < offset0) {
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
|
||||
}
|
||||
else if (offset < offset1) {
|
||||
float f = (offset - offset0) / (offset1 - offset0);
|
||||
vec4 curr_color = gsk_premultiply(get_color(0));
|
||||
vec4 next_color = gsk_premultiply(get_color(1));
|
||||
vec4 color = mix(curr_color, next_color, f);
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(1), u_alpha));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user