tor-browser

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

ps_quad.glsl (12622B)


      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 /// The common infrastructure for ps_quad_* shaders.
      6 ///
      7 /// # Memory layout
      8 ///
      9 /// The diagram below shows the the various pieces of data fectched in the vertex shader:
     10 ///
     11 ///```ascii
     12 ///                                       (int gpu buffer)
     13 ///                                       +------------------+
     14 ///                                       |Int header (ivec4)|    (float gpu buffer)
     15 ///  (instance-step vertex attr)          |                  |    +-----------+
     16 /// +-----------------------------+       | x: transform id  +--> | Transform |
     17 /// |    Quad instance (uvec4)    |  +--> | y: z id          |    +-----------+
     18 /// |                             |  |    | zw: pattern data |
     19 /// | x: int prim address        +---+    +------------------+   (float gpu buffer)
     20 /// | y: float prim address      +--------------------------> +-------------------+--------------+-+-+
     21 /// | z: quad flags               |     (float gpu buffer)    |     Quad Prim     | Quad Segment | | |
     22 /// |    edge flags               |   +--------------------+  |                   |              | | |
     23 /// |    part index               |   |     Picture task   |  | bounds            | rect         | | |
     24 /// |    segment index            |   |                    |  | clip              | uv rect      | | |
     25 /// | w: picture task address    +--> | task rect          |  | pattern transform |              | | |
     26 /// +-----------------------------+   | device pixel scale |  | color             |              | | |
     27 ///                                   | content origin     |  +-------------------+--------------+-+-+
     28 ///                                   +--------------------+
     29 ///
     30 /// To use the quad infrastructure, a shader must define the following entry
     31 /// points in the corresponding shader stages:
     32 /// - void pattern_vertex(PrimitiveInfo prim)
     33 /// - vec4 pattern_fragment(vec4 base_color)
     34 ///```
     35 
     36 #define WR_FEATURE_TEXTURE_2D
     37 
     38 #include shared,rect,transform,render_task,gpu_buffer
     39 
     40 flat varying mediump vec4 v_color;
     41 // z: is_mask
     42 // w: has edge flags
     43 // x,y are avaible for patterns to use.
     44 flat varying lowp ivec4 v_flags;
     45 #define v_flags_is_mask v_flags.z
     46 #define v_flags_has_edge_mask v_flags.w
     47 
     48 
     49 #ifndef SWGL_ANTIALIAS
     50 varying highp vec2 vLocalPos;
     51 #endif
     52 
     53 #ifdef WR_VERTEX_SHADER
     54 
     55 #define EDGE_AA_LEFT    1
     56 #define EDGE_AA_TOP     2
     57 #define EDGE_AA_RIGHT   4
     58 #define EDGE_AA_BOTTOM  8
     59 
     60 #define PART_CENTER     0
     61 #define PART_LEFT       1
     62 #define PART_TOP        2
     63 #define PART_RIGHT      3
     64 #define PART_BOTTOM     4
     65 #define PART_ALL        5
     66 
     67 #define QF_IS_OPAQUE            1
     68 #define QF_APPLY_DEVICE_CLIP    2
     69 #define QF_IGNORE_DEVICE_SCALE  4
     70 #define QF_USE_AA_SEGMENTS      8
     71 #define QF_IS_MASK              16
     72 
     73 #define INVALID_SEGMENT_INDEX   0xff
     74 
     75 #define AA_PIXEL_RADIUS 2.0
     76 
     77 PER_INSTANCE in ivec4 aData;
     78 
     79 struct QuadSegment {
     80     RectWithEndpoint rect;
     81     RectWithEndpoint uv_rect;
     82 };
     83 
     84 struct PrimitiveInfo {
     85     vec2 local_pos;
     86 
     87     RectWithEndpoint local_prim_rect;
     88     RectWithEndpoint local_clip_rect;
     89 
     90     QuadSegment segment;
     91 
     92     int edge_flags;
     93     int quad_flags;
     94     ivec2 pattern_input;
     95 };
     96 
     97 struct QuadPrimitive {
     98     RectWithEndpoint bounds;
     99     RectWithEndpoint clip;
    100     RectWithEndpoint uv_rect;
    101     vec4 pattern_scale_offset;
    102     vec4 color;
    103 };
    104 
    105 QuadSegment fetch_segment(int base, int index) {
    106     QuadSegment seg;
    107 
    108     vec4 texels[2] = fetch_from_gpu_buffer_2f(base + 5 + index * 2);
    109 
    110     seg.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
    111     seg.uv_rect = RectWithEndpoint(texels[1].xy, texels[1].zw);
    112 
    113     return seg;
    114 }
    115 
    116 QuadPrimitive fetch_primitive(int index) {
    117     QuadPrimitive prim;
    118 
    119     vec4 texels[5] = fetch_from_gpu_buffer_5f(index);
    120 
    121     prim.bounds = RectWithEndpoint(texels[0].xy, texels[0].zw);
    122     prim.clip = RectWithEndpoint(texels[1].xy, texels[1].zw);
    123     prim.uv_rect = RectWithEndpoint(texels[2].xy, texels[2].zw);
    124     prim.pattern_scale_offset = texels[3];
    125     prim.color = texels[4];
    126 
    127     return prim;
    128 }
    129 
    130 struct QuadHeader {
    131     int transform_id;
    132     int z_id;
    133     ivec2 pattern_input;
    134 };
    135 
    136 QuadHeader fetch_header(int address) {
    137     ivec4 header = fetch_from_gpu_buffer_1i(address);
    138 
    139     QuadHeader qh = QuadHeader(
    140         header.x,
    141         header.y,
    142         header.zw
    143     );
    144 
    145     return qh;
    146 }
    147 
    148 struct QuadInstance {
    149     // x
    150     int prim_address_i;
    151 
    152     // y
    153     int prim_address_f;
    154 
    155     // z
    156     int quad_flags;
    157     int edge_flags;
    158     int part_index;
    159     int segment_index;
    160 
    161     // w
    162     int picture_task_address;
    163 };
    164 
    165 QuadInstance decode_instance() {
    166     QuadInstance qi = QuadInstance(
    167         aData.x,
    168 
    169         aData.y,
    170 
    171         (aData.z >> 24) & 0xff,
    172         (aData.z >> 16) & 0xff,
    173         (aData.z >>  8) & 0xff,
    174         (aData.z >>  0) & 0xff,
    175 
    176         aData.w
    177     );
    178 
    179     return qi;
    180 }
    181 
    182 struct VertexInfo {
    183     vec2 local_pos;
    184 };
    185 
    186 VertexInfo write_vertex(vec2 local_pos,
    187                         float z,
    188                         Transform transform,
    189                         vec2 content_origin,
    190                         RectWithEndpoint task_rect,
    191                         float device_pixel_scale,
    192                         int quad_flags) {
    193     VertexInfo vi;
    194 
    195     // Transform the current vertex to world space.
    196     vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
    197 
    198     // Convert the world positions to device pixel space.
    199     vec2 device_pos = world_pos.xy * device_pixel_scale;
    200 
    201     if ((quad_flags & QF_APPLY_DEVICE_CLIP) != 0) {
    202         RectWithEndpoint device_clip_rect = RectWithEndpoint(
    203             content_origin,
    204             content_origin + task_rect.p1 - task_rect.p0
    205         );
    206 
    207         // Clip to task rect
    208         device_pos = rect_clamp(device_clip_rect, device_pos);
    209 
    210         vi.local_pos = (transform.inv_m * vec4(device_pos / device_pixel_scale, 0.0, 1.0)).xy;
    211     } else {
    212         vi.local_pos = local_pos;
    213     }
    214 
    215     // Apply offsets for the render task to get correct screen location.
    216     vec2 final_offset = -content_origin + task_rect.p0;
    217 
    218     gl_Position = uTransform * vec4(device_pos + final_offset * world_pos.w, z * world_pos.w, world_pos.w);
    219 
    220     return vi;
    221 }
    222 
    223 float edge_aa_offset(int edge, int flags) {
    224     return ((flags & edge) != 0) ? AA_PIXEL_RADIUS : 0.0;
    225 }
    226 
    227 void pattern_vertex(PrimitiveInfo prim);
    228 
    229 vec2 scale_offset_map_point(vec4 scale_offset, vec2 p) {
    230     return p * scale_offset.xy + scale_offset.zw;
    231 }
    232 
    233 RectWithEndpoint scale_offset_map_rect(vec4 scale_offset, RectWithEndpoint r) {
    234     vec2 p0 = scale_offset_map_point(scale_offset, r.p0);
    235     vec2 p1 = scale_offset_map_point(scale_offset, r.p1);
    236     return RectWithEndpoint(
    237         min(p0, p1),
    238         max(p0, p1)
    239     );
    240 }
    241 
    242 PrimitiveInfo quad_primive_info(void) {
    243     QuadInstance qi = decode_instance();
    244 
    245     QuadHeader qh = fetch_header(qi.prim_address_i);
    246     Transform transform = fetch_transform(qh.transform_id);
    247     PictureTask task = fetch_picture_task(qi.picture_task_address);
    248     QuadPrimitive prim = fetch_primitive(qi.prim_address_f);
    249     float z = float(qh.z_id);
    250 
    251     QuadSegment seg;
    252     if (qi.segment_index == INVALID_SEGMENT_INDEX) {
    253         seg.rect = prim.bounds;
    254         seg.uv_rect = prim.uv_rect;
    255     } else {
    256         seg = fetch_segment(qi.prim_address_f, qi.segment_index);
    257     }
    258 
    259     // The local space rect that we will draw, which is effectively:
    260     //  - The tile within the primitive we will draw
    261     //  - Intersected with any local-space clip rect(s)
    262     //  - Expanded for AA edges where appropriate
    263     RectWithEndpoint local_coverage_rect = seg.rect;
    264 
    265     // Apply local clip rect
    266     local_coverage_rect.p0 = max(local_coverage_rect.p0, prim.clip.p0);
    267     local_coverage_rect.p1 = min(local_coverage_rect.p1, prim.clip.p1);
    268     local_coverage_rect.p1 = max(local_coverage_rect.p0, local_coverage_rect.p1);
    269 
    270     switch (qi.part_index) {
    271         case PART_LEFT:
    272             local_coverage_rect.p1.x = local_coverage_rect.p0.x + AA_PIXEL_RADIUS;
    273 #ifdef SWGL_ANTIALIAS
    274             swgl_antiAlias(EDGE_AA_LEFT);
    275 #else
    276             local_coverage_rect.p0.x -= AA_PIXEL_RADIUS;
    277             local_coverage_rect.p0.y -= AA_PIXEL_RADIUS;
    278             local_coverage_rect.p1.y += AA_PIXEL_RADIUS;
    279 #endif
    280             break;
    281         case PART_TOP:
    282             local_coverage_rect.p0.x = local_coverage_rect.p0.x + AA_PIXEL_RADIUS;
    283             local_coverage_rect.p1.x = local_coverage_rect.p1.x - AA_PIXEL_RADIUS;
    284             local_coverage_rect.p1.y = local_coverage_rect.p0.y + AA_PIXEL_RADIUS;
    285 #ifdef SWGL_ANTIALIAS
    286             swgl_antiAlias(EDGE_AA_TOP);
    287 #else
    288             local_coverage_rect.p0.y -= AA_PIXEL_RADIUS;
    289 #endif
    290             break;
    291         case PART_RIGHT:
    292             local_coverage_rect.p0.x = local_coverage_rect.p1.x - AA_PIXEL_RADIUS;
    293 #ifdef SWGL_ANTIALIAS
    294             swgl_antiAlias(EDGE_AA_RIGHT);
    295 #else
    296             local_coverage_rect.p1.x += AA_PIXEL_RADIUS;
    297             local_coverage_rect.p0.y -= AA_PIXEL_RADIUS;
    298             local_coverage_rect.p1.y += AA_PIXEL_RADIUS;
    299 #endif
    300             break;
    301         case PART_BOTTOM:
    302             local_coverage_rect.p0.x = local_coverage_rect.p0.x + AA_PIXEL_RADIUS;
    303             local_coverage_rect.p1.x = local_coverage_rect.p1.x - AA_PIXEL_RADIUS;
    304             local_coverage_rect.p0.y = local_coverage_rect.p1.y - AA_PIXEL_RADIUS;
    305 #ifdef SWGL_ANTIALIAS
    306             swgl_antiAlias(EDGE_AA_BOTTOM);
    307 #else
    308             local_coverage_rect.p1.y += AA_PIXEL_RADIUS;
    309 #endif
    310             break;
    311         case PART_CENTER:
    312             local_coverage_rect.p0.x += edge_aa_offset(EDGE_AA_LEFT, qi.edge_flags);
    313             local_coverage_rect.p1.x -= edge_aa_offset(EDGE_AA_RIGHT, qi.edge_flags);
    314             local_coverage_rect.p0.y += edge_aa_offset(EDGE_AA_TOP, qi.edge_flags);
    315             local_coverage_rect.p1.y -= edge_aa_offset(EDGE_AA_BOTTOM, qi.edge_flags);
    316             break;
    317         case PART_ALL:
    318         default:
    319 #ifdef SWGL_ANTIALIAS
    320             swgl_antiAlias(qi.edge_flags);
    321 #else
    322             local_coverage_rect.p0.x -= edge_aa_offset(EDGE_AA_LEFT, qi.edge_flags);
    323             local_coverage_rect.p1.x += edge_aa_offset(EDGE_AA_RIGHT, qi.edge_flags);
    324             local_coverage_rect.p0.y -= edge_aa_offset(EDGE_AA_TOP, qi.edge_flags);
    325             local_coverage_rect.p1.y += edge_aa_offset(EDGE_AA_BOTTOM, qi.edge_flags);
    326 #endif
    327             break;
    328     }
    329 
    330     vec2 local_pos = mix(local_coverage_rect.p0, local_coverage_rect.p1, aPosition);
    331 
    332     float device_pixel_scale = task.device_pixel_scale;
    333     if ((qi.quad_flags & QF_IGNORE_DEVICE_SCALE) != 0) {
    334         device_pixel_scale = 1.0f;
    335     }
    336 
    337     VertexInfo vi = write_vertex(
    338         local_pos,
    339         z,
    340         transform,
    341         task.content_origin,
    342         task.task_rect,
    343         device_pixel_scale,
    344         qi.quad_flags
    345     );
    346 
    347     v_color = prim.color;
    348 
    349     vec4 pattern_tx = prim.pattern_scale_offset;
    350     seg.rect = scale_offset_map_rect(pattern_tx, seg.rect);
    351 
    352     return PrimitiveInfo(
    353         scale_offset_map_point(pattern_tx, vi.local_pos),
    354         scale_offset_map_rect(pattern_tx, prim.bounds),
    355         scale_offset_map_rect(pattern_tx, prim.clip),
    356         seg,
    357         qi.edge_flags,
    358         qi.quad_flags,
    359         qh.pattern_input
    360     );
    361 }
    362 
    363 void antialiasing_vertex(PrimitiveInfo prim) {
    364 #ifndef SWGL_ANTIALIAS
    365     // This does the setup that is required for init_tranform_vs.
    366     RectWithEndpoint xf_bounds = RectWithEndpoint(
    367         max(prim.local_prim_rect.p0, prim.local_clip_rect.p0),
    368         min(prim.local_prim_rect.p1, prim.local_clip_rect.p1)
    369     );
    370     vTransformBounds = vec4(xf_bounds.p0, xf_bounds.p1);
    371 
    372     vLocalPos = prim.local_pos;
    373 
    374     if (prim.edge_flags == 0) {
    375         v_flags_has_edge_mask = 0;
    376     } else {
    377         v_flags_has_edge_mask = 1;
    378     }
    379 #endif
    380 }
    381 
    382 void main() {
    383     PrimitiveInfo prim = quad_primive_info();
    384 
    385     if ((prim.quad_flags & QF_IS_MASK) != 0) {
    386         v_flags_is_mask = 1;
    387     } else {
    388         v_flags_is_mask = 0;
    389     }
    390 
    391     antialiasing_vertex(prim);
    392     pattern_vertex(prim);
    393 }
    394 #endif
    395 
    396 #ifdef WR_FRAGMENT_SHADER
    397 vec4 pattern_fragment(vec4 base_color);
    398 
    399 float antialiasing_fragment() {
    400     float alpha = 1.0;
    401 #ifndef SWGL_ANTIALIAS
    402     if (v_flags_has_edge_mask != 0) {
    403         alpha = rectangle_aa_fragment(vLocalPos);
    404     }
    405 #endif
    406     return alpha;
    407 }
    408 
    409 void main() {
    410     vec4 base_color = v_color;
    411     base_color *= antialiasing_fragment();
    412     vec4 output_color = pattern_fragment(base_color);
    413 
    414     if (v_flags_is_mask != 0) {
    415         output_color = output_color.rrrr;
    416     }
    417 
    418     oFragColor = output_color;
    419 }
    420 
    421 #endif