tor-browser

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

brush.glsl (10015B)


      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 /// # Brush vertex shaders memory layout
      6 ///
      7 /// The overall memory layout is the same for all brush shaders.
      8 ///
      9 /// The vertex shader receives a minimal amount of data from vertex attributes (packed into a single
     10 /// ivec4 per instance) and the rest is fetched from various uniform samplers using offsets decoded
     11 /// from the vertex attributes.
     12 ///
     13 /// The diagram below shows the the various pieces of data fectched in the vertex shader:
     14 ///
     15 ///```ascii
     16 ///                                                                         (sPrimitiveHeadersI)
     17 ///                          (VBO)                                     +-----------------------+
     18 /// +----------------------------+      +----------------------------> | Int header            |
     19 /// | Instance vertex attributes |      |        (sPrimitiveHeadersF)  |                       |
     20 /// |                            |      |     +---------------------+  |   z                   |
     21 /// | x: prim_header_address    +-------+---> | Float header        |  |   specific_address  +-----+
     22 /// | y: picture_task_address   +---------+   |                     |  |   transform_address +---+ |
     23 /// |    clip_address           +-----+   |   |    local_rect       |  |   user_data           | | |
     24 /// | z: flags                   |    |   |   |    local_clip_rect  |  +-----------------------+ | |
     25 /// |    segment_index           |    |   |   +---------------------+                            | |
     26 /// | w: resource_address       +--+  |   |                                                      | |
     27 /// +----------------------------+ |  |   |                             (float gpu buffer)       | |
     28 ///                                |  |   |   (float gpu buffer)         +------------+          | |
     29 ///                                |  |   |   +---------------+          | Transform  | <--------+ |
     30 ///           (float gpu buffer)   |  |   +-> | Picture task  |          +------------+            |
     31 ///            +-------------+     |  |       |               |                                    |
     32 ///            |  Resource   | <---+  |       |         ...   |                                    |
     33 ///            |             |        |       +---------------+   +--------------------------------+
     34 ///            |             |        |                           |
     35 ///            +-------------+        |       (float gpu buffer)  v                (float gpu buffer)
     36 ///                                   |       +---------------+  +--------------+---------------+-+-+
     37 ///                                   +-----> | Clip area     |  | Brush data   |  Segment data | | |
     38 ///                                           |               |  |              |               | | |
     39 ///                                           |         ...   |  |         ...  |          ...  | | | ...
     40 ///                                           +---------------+  +--------------+---------------+-+-+
     41 ///```
     42 ///
     43 /// - Segment data address is obtained by combining the address stored in the int header and the
     44 ///   segment index decoded from the vertex attributes.
     45 /// - Resource data is optional, some brush types (such as images) store some extra data there while
     46 ///   other brush types don't use it.
     47 ///
     48 
     49 #if (defined(WR_FEATURE_ALPHA_PASS) || defined(WR_FEATURE_ANTIALIASING)) && !defined(SWGL_ANTIALIAS)
     50 varying highp vec2 v_local_pos;
     51 #endif
     52 
     53 #ifdef WR_VERTEX_SHADER
     54 
     55 void brush_vs(
     56     VertexInfo vi,
     57     int prim_address,
     58     RectWithEndpoint local_rect,
     59     RectWithEndpoint segment_rect,
     60     ivec4 prim_user_data,
     61     int specific_resource_address,
     62     mat4 transform,
     63     PictureTask pic_task,
     64     int brush_flags,
     65     vec4 segment_data
     66 );
     67 
     68 // Forward-declare the text vertex shader entry point which is currently
     69 // different from other brushes.
     70 void text_shader_main(
     71     Instance instance,
     72     PrimitiveHeader ph,
     73     Transform transform,
     74     PictureTask task,
     75     ClipArea clip_area
     76 );
     77 
     78 #define VECS_PER_SEGMENT                    2
     79 
     80 #define BRUSH_FLAG_PERSPECTIVE_INTERPOLATION    1
     81 #define BRUSH_FLAG_SEGMENT_RELATIVE             2
     82 #define BRUSH_FLAG_SEGMENT_REPEAT_X             4
     83 #define BRUSH_FLAG_SEGMENT_REPEAT_Y             8
     84 #define BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND      16
     85 #define BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND      32
     86 #define BRUSH_FLAG_SEGMENT_REPEAT_X_CENTERED   64
     87 #define BRUSH_FLAG_SEGMENT_REPEAT_Y_CENTERED  128
     88 #define BRUSH_FLAG_SEGMENT_NINEPATCH_MIDDLE   256
     89 #define BRUSH_FLAG_TEXEL_RECT                 512
     90 #define BRUSH_FLAG_FORCE_AA                  1024
     91 #define BRUSH_FLAG_NORMALIZED_UVS            2048
     92 
     93 #define INVALID_SEGMENT_INDEX                   0xffff
     94 
     95 void brush_shader_main_vs(
     96     Instance instance,
     97     PrimitiveHeader ph,
     98     Transform transform,
     99     PictureTask pic_task,
    100     ClipArea clip_area
    101 ) {
    102     int edge_flags = (instance.flags >> 12) & 0xf;
    103     int brush_flags = instance.flags & 0xfff;
    104 
    105     // Fetch the segment of this brush primitive we are drawing.
    106     vec4 segment_data;
    107     RectWithEndpoint segment_rect;
    108     if (instance.segment_index == INVALID_SEGMENT_INDEX) {
    109         segment_rect = ph.local_rect;
    110         segment_data = vec4(0.0);
    111     } else {
    112         // See BrushSegmentGpuData
    113         int segment_address = ph.specific_prim_address +
    114                               VECS_PER_SPECIFIC_BRUSH +
    115                               instance.segment_index * VECS_PER_SEGMENT;
    116 
    117         vec4[2] segment_info = fetch_from_gpu_buffer_2f(segment_address);
    118         segment_rect = RectWithEndpoint(segment_info[0].xy, segment_info[0].zw);
    119         segment_rect.p0 += ph.local_rect.p0;
    120         segment_rect.p1 += ph.local_rect.p0;
    121         segment_data = segment_info[1];
    122     }
    123 
    124     // Most of the time this is the segment rect, but when doing the edge AA
    125     // it is inflated.
    126     RectWithEndpoint adjusted_segment_rect = segment_rect;
    127 
    128     bool antialiased = !transform.is_axis_aligned || ((brush_flags & BRUSH_FLAG_FORCE_AA) != 0);
    129 
    130     // Write the normal vertex information out.
    131     if (antialiased) {
    132         adjusted_segment_rect = clip_and_init_antialiasing(
    133             segment_rect,
    134             ph.local_rect,
    135             ph.local_clip_rect,
    136             edge_flags,
    137             ph.z,
    138             transform,
    139             pic_task
    140         );
    141 
    142         // The clip was taken into account in clip_and_init_antialiasing, remove
    143         // it so that it doesn't interfere with the aa.
    144         ph.local_clip_rect.p0 = vec2(-1.0e16);
    145         ph.local_clip_rect.p1 = vec2(1.0e16);
    146     } else {
    147         // The common case for most CSS content.
    148 
    149         // TODO(gw): transform bounds may be referenced by
    150         //           the fragment shader when running in
    151         //           the alpha pass, even on non-transformed
    152         //           items. For now, just ensure it has no
    153         //           effect. We can tidy this up as we move
    154         //           more items to be brush shaders.
    155 #if defined(WR_FEATURE_ALPHA_PASS) && !defined(SWGL_ANTIALIAS)
    156         rectangle_aa_vertex(vec4(vec2(-1.0e16), vec2(1.0e16)));
    157 #endif
    158     }
    159 
    160     // Select the corner of the local rect that we are processing.
    161     vec2 local_pos = mix(adjusted_segment_rect.p0, adjusted_segment_rect.p1, aPosition.xy);
    162 
    163     VertexInfo vi = write_vertex(
    164         local_pos,
    165         ph.local_clip_rect,
    166         ph.z,
    167         transform,
    168         pic_task
    169     );
    170 
    171     // For brush instances in the alpha pass, always write
    172     // out clip information.
    173     // TODO(gw): It's possible that we might want alpha
    174     //           shaders that don't clip in the future,
    175     //           but it's reasonable to assume that one
    176     //           implies the other, for now.
    177     // SW-WR may decay some requests for alpha-pass shaders to
    178     // the opaque version if only the clip-mask is required. In
    179     // that case the opaque vertex shader must still write out
    180     // the clip information, which is cheap to do for SWGL.
    181 #if defined(WR_FEATURE_ALPHA_PASS) || defined(SWGL_CLIP_MASK)
    182     write_clip(
    183         vi.world_pos,
    184         clip_area,
    185         pic_task
    186     );
    187 #endif
    188 
    189     // Run the specific brush VS code to write interpolators.
    190     brush_vs(
    191         vi,
    192         ph.specific_prim_address,
    193         ph.local_rect,
    194         segment_rect,
    195         ph.user_data,
    196         instance.resource_address,
    197         transform.m,
    198         pic_task,
    199         brush_flags,
    200         segment_data
    201     );
    202 
    203 #if (defined(WR_FEATURE_ALPHA_PASS) || defined(WR_FEATURE_ANTIALIASING)) && !defined(SWGL_ANTIALIAS)
    204     v_local_pos = vi.local_pos;
    205 #endif
    206 }
    207 
    208 #ifndef WR_VERTEX_SHADER_MAIN_FUNCTION
    209 // If the entry-point was not overridden before including the brush shader,
    210 // use the default one.
    211 #define WR_VERTEX_SHADER_MAIN_FUNCTION brush_shader_main_vs
    212 #endif
    213 
    214 void main(void) {
    215 
    216     Instance instance = decode_instance_attributes();
    217     PrimitiveHeader ph = fetch_prim_header(instance.prim_header_address);
    218     Transform transform = fetch_transform(ph.transform_id);
    219     PictureTask task = fetch_picture_task(ph.picture_task_address);
    220     ClipArea clip_area = fetch_clip_area(instance.clip_address);
    221 
    222     WR_VERTEX_SHADER_MAIN_FUNCTION(instance, ph, transform, task, clip_area);
    223 }
    224 
    225 #endif // WR_VERTEX_SHADER
    226 
    227 #ifdef WR_FRAGMENT_SHADER
    228 
    229 float antialias_brush() {
    230 #if (defined(WR_FEATURE_ALPHA_PASS) || defined(WR_FEATURE_ANTIALIASING)) && !defined(SWGL_ANTIALIAS)
    231     return rectangle_aa_fragment(v_local_pos);
    232 #else
    233     return 1.0;
    234 #endif
    235 }
    236 
    237 Fragment brush_fs();
    238 
    239 void main(void) {
    240 #ifdef WR_FEATURE_DEBUG_OVERDRAW
    241     oFragColor = WR_DEBUG_OVERDRAW_COLOR;
    242 #else
    243 
    244     Fragment frag = brush_fs();
    245 
    246 #ifdef WR_FEATURE_ALPHA_PASS
    247     // Apply the clip mask
    248     float clip_alpha = do_clip();
    249 
    250     frag.color *= clip_alpha;
    251 
    252     #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
    253         oFragBlend = frag.blend * clip_alpha;
    254     #endif
    255 #endif
    256 
    257     write_output(frag.color);
    258 #endif
    259 }
    260 #endif