gecko-dev/gfx/webrender/res/brush_line.glsl
Kartikaya Gupta 9599c98878 Bug 1426116 - Update webrender to commit a422f907be948b92bf5c7003a01f7744391a795e. r=jrmuizel
MozReview-Commit-ID: 1PTMg1c0KiC

--HG--
extra : rebase_source : 49180fae34c1aa54d71f1cc060377c842834c3ac
2018-01-08 09:19:23 -05:00

230 lines
7.2 KiB
GLSL

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 2
#include shared,prim_shared,brush
varying vec2 vLocalPos;
flat varying vec4 vColor;
flat varying int vStyle;
flat varying float vAxisSelect;
flat varying vec4 vParams;
flat varying vec2 vLocalOrigin;
#ifdef WR_VERTEX_SHADER
#define LINE_ORIENTATION_VERTICAL 0
#define LINE_ORIENTATION_HORIZONTAL 1
struct Line {
vec4 color;
float wavyLineThickness;
float style;
float orientation;
};
Line fetch_line(int address) {
vec4 data[2] = fetch_from_resource_cache_2(address);
return Line(data[0], data[1].x, data[1].y, data[1].z);
}
void brush_vs(
int prim_address,
vec2 local_pos,
RectWithSize local_rect,
ivec2 user_data,
PictureTask pic_task
) {
vLocalPos = local_pos;
Line line = fetch_line(prim_address);
switch (int(abs(pic_task.pic_kind_and_raster_mode))) {
case PIC_TYPE_TEXT_SHADOW:
vColor = pic_task.color;
break;
default:
vColor = line.color;
break;
}
vec2 pos, size;
switch (int(line.orientation)) {
case LINE_ORIENTATION_HORIZONTAL:
vAxisSelect = 0.0;
pos = local_rect.p0;
size = local_rect.size;
break;
case LINE_ORIENTATION_VERTICAL:
vAxisSelect = 1.0;
pos = local_rect.p0.yx;
size = local_rect.size.yx;
break;
}
vLocalOrigin = pos;
vStyle = int(line.style);
switch (vStyle) {
case LINE_STYLE_SOLID: {
break;
}
case LINE_STYLE_DASHED: {
float dash_length = size.y * 3.0;
vParams = vec4(2.0 * dash_length, // period
dash_length, // dash length
0.0,
0.0);
break;
}
case LINE_STYLE_DOTTED: {
float diameter = size.y;
float period = diameter * 2.0;
float center_line = pos.y + 0.5 * size.y;
float max_x = floor(size.x / period) * period;
vParams = vec4(period,
diameter / 2.0, // radius
center_line,
max_x);
break;
}
case LINE_STYLE_WAVY: {
// This logic copied from gecko to get the same results
float line_thickness = max(line.wavyLineThickness, 1.0);
// Difference in height between peaks and troughs
// (and since slopes are 45 degrees, the length of each slope)
float slope_length = size.y - line_thickness;
// Length of flat runs
float flat_length = max((line_thickness - 1.0) * 2.0, 1.0);
vParams = vec4(line_thickness / 2.0,
slope_length,
flat_length,
size.y);
break;
}
}
}
#endif
#ifdef WR_FRAGMENT_SHADER
#define MAGIC_WAVY_LINE_AA_SNAP 0.7
float det(vec2 a, vec2 b) {
return a.x * b.y - b.x * a.y;
}
// From: http://research.microsoft.com/en-us/um/people/hoppe/ravg.pdf
vec2 get_distance_vector(vec2 b0, vec2 b1, vec2 b2) {
float a = det(b0, b2);
float b = 2.0 * det(b1, b0);
float d = 2.0 * det(b2, b1);
float f = b * d - a * a;
vec2 d21 = b2 - b1;
vec2 d10 = b1 - b0;
vec2 d20 = b2 - b0;
vec2 gf = 2.0 * (b *d21 + d * d10 + a * d20);
gf = vec2(gf.y,-gf.x);
vec2 pp = -f * gf / dot(gf, gf);
vec2 d0p = b0 - pp;
float ap = det(d0p, d20);
float bp = 2.0 * det(d10, d0p);
float t = clamp((ap + bp) / (2.0 * a + b + d), 0.0, 1.0);
return mix(mix(b0, b1, t), mix(b1,b2,t), t);
}
// Approximate distance from point to quadratic bezier.
float approx_distance(vec2 p, vec2 b0, vec2 b1, vec2 b2) {
return length(get_distance_vector(b0 - p, b1 - p, b2 - p));
}
vec4 brush_fs() {
// Find the appropriate distance to apply the step over.
vec2 local_pos = vLocalPos;
float aa_range = compute_aa_range(local_pos);
float alpha = 1.0;
// Select the x/y coord, depending on which axis this edge is.
vec2 pos = mix(local_pos.xy, local_pos.yx, vAxisSelect);
switch (vStyle) {
case LINE_STYLE_SOLID: {
break;
}
case LINE_STYLE_DASHED: {
// Get the main-axis position relative to closest dot or dash.
float x = mod(pos.x - vLocalOrigin.x, vParams.x);
// Calculate dash alpha (on/off) based on dash length
alpha = step(x, vParams.y);
break;
}
case LINE_STYLE_DOTTED: {
// Get the main-axis position relative to closest dot or dash.
float x = mod(pos.x - vLocalOrigin.x, vParams.x);
// Get the dot alpha
vec2 dot_relative_pos = vec2(x, pos.y) - vParams.yz;
float dot_distance = length(dot_relative_pos) - vParams.y;
alpha = distance_aa(aa_range, dot_distance);
// Clip off partial dots
alpha *= step(pos.x - vLocalOrigin.x, vParams.w);
break;
}
case LINE_STYLE_WAVY: {
vec2 normalized_local_pos = pos - vLocalOrigin.xy;
float half_line_thickness = vParams.x;
float slope_length = vParams.y;
float flat_length = vParams.z;
float vertical_bounds = vParams.w;
// Our pattern is just two slopes and two flats
float half_period = slope_length + flat_length;
float mid_height = vertical_bounds / 2.0;
float peak_offset = mid_height - half_line_thickness;
// Flip the wave every half period
float flip = -2.0 * (step(mod(normalized_local_pos.x, 2.0 * half_period), half_period) - 0.5);
// float flip = -1.0;
peak_offset *= flip;
float peak_height = mid_height + peak_offset;
// Convert pos to a local position within one half period
normalized_local_pos.x = mod(normalized_local_pos.x, half_period);
// Compute signed distance to the 3 lines that make up an arc
float dist1 = distance_to_line(vec2(0.0, peak_height),
vec2(1.0, -flip),
normalized_local_pos);
float dist2 = distance_to_line(vec2(0.0, peak_height),
vec2(0, -flip),
normalized_local_pos);
float dist3 = distance_to_line(vec2(flat_length, peak_height),
vec2(-1.0, -flip),
normalized_local_pos);
float dist = abs(max(max(dist1, dist2), dist3));
// Apply AA based on the thickness of the wave
alpha = distance_aa(aa_range, dist - half_line_thickness);
// Disable AA for thin lines
if (half_line_thickness <= 1.0) {
alpha = 1.0 - step(alpha, MAGIC_WAVY_LINE_AA_SNAP);
}
break;
}
}
return vColor * alpha;
}
#endif