tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ps_quad_mask.glsl (6331B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2  * License, v. 2.0. If a copy of the MPL was not distributed with this
      3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /// This shader applies a (rounded) rectangle mask to the content of the framebuffer.
      6 
      7 #include ps_quad,ellipse
      8 
      9 varying highp vec4 vClipLocalPos;
     10 
     11 #ifdef WR_FEATURE_FAST_PATH
     12 flat varying highp vec4 v_clip_radii;
     13 flat varying highp vec2 v_clip_size;
     14 #else
     15 flat varying highp vec4 vClipCenter_Radius_TL;
     16 flat varying highp vec4 vClipCenter_Radius_TR;
     17 flat varying highp vec4 vClipCenter_Radius_BR;
     18 flat varying highp vec4 vClipCenter_Radius_BL;
     19 // We pack 4 vec3 clip planes into 3 vec4 to save a varying slot.
     20 flat varying highp vec4 vClipPlane_A;
     21 flat varying highp vec4 vClipPlane_B;
     22 flat varying highp vec4 vClipPlane_C;
     23 #endif
     24 flat varying highp vec2 vClipMode;
     25 
     26 #ifdef WR_VERTEX_SHADER
     27 
     28 PER_INSTANCE in ivec4 aClipData;
     29 
     30 #define CLIP_SPACE_RASTER       0
     31 #define CLIP_SPACE_PRIMITIVE    1
     32 
     33 struct Clip {
     34     RectWithEndpoint rect;
     35 #ifdef WR_FEATURE_FAST_PATH
     36     vec4 radii;
     37 #else
     38     vec4 radii_top;
     39     vec4 radii_bottom;
     40 #endif
     41     float mode;
     42     int space;
     43 };
     44 
     45 Clip fetch_clip(int index) {
     46     Clip clip;
     47 
     48     clip.space = aClipData.z;
     49 
     50 #ifdef WR_FEATURE_FAST_PATH
     51     vec4 texels[3] = fetch_from_gpu_buffer_3f(index);
     52     clip.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
     53     clip.radii = texels[1];
     54     clip.mode = texels[2].x;
     55 #else
     56     vec4 texels[4] = fetch_from_gpu_buffer_4f(index);
     57     clip.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
     58     clip.radii_top = texels[1];
     59     clip.radii_bottom = texels[2];
     60     clip.mode = texels[3].x;
     61 #endif
     62 
     63     return clip;
     64 }
     65 
     66 void pattern_vertex(PrimitiveInfo prim_info) {
     67 
     68     Clip clip = fetch_clip(aClipData.y);
     69     Transform clip_transform = fetch_transform(aClipData.x);
     70 
     71     vClipLocalPos = clip_transform.m * vec4(prim_info.local_pos, 0.0, 1.0);
     72 
     73 #ifndef WR_FEATURE_FAST_PATH
     74     if (clip.space == CLIP_SPACE_RASTER) {
     75         vTransformBounds = vec4(clip.rect.p0, clip.rect.p1);
     76     } else {
     77         RectWithEndpoint xf_bounds = RectWithEndpoint(
     78             max(clip.rect.p0, prim_info.local_clip_rect.p0),
     79             min(clip.rect.p1, prim_info.local_clip_rect.p1)
     80         );
     81         vTransformBounds = vec4(xf_bounds.p0, xf_bounds.p1);
     82     }
     83 #endif
     84 
     85     vClipMode.x = clip.mode;
     86 
     87 #ifdef WR_FEATURE_FAST_PATH
     88     // If the radii are uniform, we can use a simpler 2d signed distance
     89     // function to get a rounded rect clip.
     90     vec2 half_size = 0.5 * (clip.rect.p1 - clip.rect.p0);
     91     // Center the position in the box.
     92     vClipLocalPos.xy -= (half_size + clip.rect.p0) * vClipLocalPos.w;
     93     v_clip_size = half_size;
     94     v_clip_radii = clip.radii;
     95 #else
     96     vec2 r_tl = clip.radii_top.xy;
     97     vec2 r_tr = clip.radii_top.zw;
     98     vec2 r_br = clip.radii_bottom.zw;
     99     vec2 r_bl = clip.radii_bottom.xy;
    100 
    101     vClipCenter_Radius_TL = vec4(clip.rect.p0 + r_tl,
    102                                  inverse_radii_squared(r_tl));
    103 
    104     vClipCenter_Radius_TR = vec4(clip.rect.p1.x - r_tr.x,
    105                                  clip.rect.p0.y + r_tr.y,
    106                                  inverse_radii_squared(r_tr));
    107 
    108     vClipCenter_Radius_BR = vec4(clip.rect.p1 - r_br,
    109                                  inverse_radii_squared(r_br));
    110 
    111     vClipCenter_Radius_BL = vec4(clip.rect.p0.x + r_bl.x,
    112                                  clip.rect.p1.y - r_bl.y,
    113                                  inverse_radii_squared(r_bl));
    114 
    115     // We need to know the half-spaces of the corners separate from the center
    116     // and radius. We compute a point that falls on the diagonal (which is just
    117     // an inner vertex pushed out along one axis, but not on both) to get the
    118     // plane offset of the half-space. We also compute the direction vector of
    119     // the half-space, which is a perpendicular vertex (-y,x) of the vector of
    120     // the diagonal. We leave the scales of the vectors unchanged.
    121     vec2 n_tl = -r_tl.yx;
    122     vec2 n_tr = vec2(r_tr.y, -r_tr.x);
    123     vec2 n_br = r_br.yx;
    124     vec2 n_bl = vec2(-r_bl.y, r_bl.x);
    125     vec3 tl = vec3(n_tl,
    126                    dot(n_tl, vec2(clip.rect.p0.x, clip.rect.p0.y + r_tl.y)));
    127     vec3 tr = vec3(n_tr,
    128                    dot(n_tr, vec2(clip.rect.p1.x - r_tr.x, clip.rect.p0.y)));
    129     vec3 br = vec3(n_br,
    130                    dot(n_br, vec2(clip.rect.p1.x, clip.rect.p1.y - r_br.y)));
    131     vec3 bl = vec3(n_bl,
    132                    dot(n_bl, vec2(clip.rect.p0.x + r_bl.x, clip.rect.p1.y)));
    133 
    134     vClipPlane_A = vec4(tl.x, tl.y, tl.z, tr.x);
    135     vClipPlane_B = vec4(tr.y, tr.z, br.x, br.y);
    136     vClipPlane_C = vec4(br.z, bl.x, bl.y, bl.z);
    137 #endif
    138 
    139 }
    140 #endif
    141 
    142 #ifdef WR_FRAGMENT_SHADER
    143 
    144 #ifdef WR_FEATURE_FAST_PATH
    145 // See https://www.shadertoy.com/view/4llXD7
    146 // Notes:
    147 //  * pos is centered in the origin (so 0,0 is the center of the box).
    148 //  * The border radii must not be larger than half_box_size.
    149 float sd_round_box(in vec2 pos, in vec2 half_box_size, in vec4 radii) {
    150     radii.xy = (pos.x > 0.0) ? radii.xy : radii.zw;
    151     radii.x  = (pos.y > 0.0) ? radii.x  : radii.y;
    152     vec2 q = abs(pos) - half_box_size + radii.x;
    153     return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radii.x;
    154 }
    155 #endif
    156 
    157 vec4 pattern_fragment(vec4 _base_color) {
    158     vec2 clip_local_pos = vClipLocalPos.xy / vClipLocalPos.w;
    159     float aa_range = compute_aa_range(clip_local_pos);
    160 
    161 #ifdef WR_FEATURE_FAST_PATH
    162     float dist = sd_round_box(clip_local_pos, v_clip_size, v_clip_radii);
    163 #else
    164     vec3 plane_tl = vec3(vClipPlane_A.x, vClipPlane_A.y, vClipPlane_A.z);
    165     vec3 plane_tr = vec3(vClipPlane_A.w, vClipPlane_B.x, vClipPlane_B.y);
    166     vec3 plane_br = vec3(vClipPlane_B.z, vClipPlane_B.w, vClipPlane_C.x);
    167     vec3 plane_bl = vec3(vClipPlane_C.y, vClipPlane_C.z, vClipPlane_C.w);
    168 
    169     float dist = distance_to_rounded_rect(
    170         clip_local_pos,
    171         plane_tl,
    172         vClipCenter_Radius_TL,
    173         plane_tr,
    174         vClipCenter_Radius_TR,
    175         plane_br,
    176         vClipCenter_Radius_BR,
    177         plane_bl,
    178         vClipCenter_Radius_BL,
    179         vTransformBounds
    180     );
    181 #endif
    182 
    183     // Compute AA for the given dist and range.
    184     float alpha = distance_aa(aa_range, dist);
    185 
    186     // Select alpha or inverse alpha depending on clip in/out.
    187     float final_alpha = mix(alpha, 1.0 - alpha, vClipMode.x);
    188 
    189     return vec4(final_alpha);
    190 }
    191 #endif