tor-browser

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

prim_shared.glsl (8449B)


      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 #include rect,render_task,transform,image_source
      6 
      7 #define EXTEND_MODE_CLAMP  0
      8 #define EXTEND_MODE_REPEAT 1
      9 
     10 #define SUBPX_DIR_NONE        0
     11 #define SUBPX_DIR_HORIZONTAL  1
     12 #define SUBPX_DIR_VERTICAL    2
     13 
     14 #define RASTER_LOCAL            0
     15 #define RASTER_SCREEN           1
     16 
     17 uniform sampler2D sClipMask;
     18 
     19 #ifndef SWGL_CLIP_MASK
     20 // TODO: convert back to RectWithEndpoint if driver issues are resolved, if ever.
     21 flat varying mediump vec4 vClipMaskUvBounds;
     22 varying highp vec2 vClipMaskUv;
     23 #endif
     24 
     25 #ifdef WR_VERTEX_SHADER
     26 
     27 #define COLOR_MODE_ALPHA                0
     28 #define COLOR_MODE_SUBPX_DUAL_SOURCE    1
     29 #define COLOR_MODE_BITMAP_SHADOW        2
     30 #define COLOR_MODE_COLOR_BITMAP         3
     31 #define COLOR_MODE_IMAGE                4
     32 #define COLOR_MODE_MULTIPLY_DUAL_SOURCE 5
     33 
     34 uniform HIGHP_SAMPLER_FLOAT sampler2D sPrimitiveHeadersF;
     35 uniform HIGHP_SAMPLER_FLOAT isampler2D sPrimitiveHeadersI;
     36 
     37 // Instanced attributes
     38 PER_INSTANCE in ivec4 aData;
     39 
     40 #define VECS_PER_PRIM_HEADER_F 2U
     41 #define VECS_PER_PRIM_HEADER_I 2U
     42 
     43 struct Instance
     44 {
     45     int prim_header_address;
     46     int clip_address;
     47     int segment_index;
     48     int flags;
     49     int resource_address;
     50     int brush_kind;
     51 };
     52 
     53 Instance decode_instance_attributes() {
     54     Instance instance;
     55 
     56     instance.prim_header_address = aData.x;
     57     instance.clip_address = aData.y;
     58     instance.segment_index = aData.z & 0xffff;
     59     instance.flags = aData.z >> 16;
     60     instance.resource_address = aData.w & 0xffffff;
     61     instance.brush_kind = aData.w >> 24;
     62 
     63     return instance;
     64 }
     65 
     66 struct PrimitiveHeader {
     67     RectWithEndpoint local_rect;
     68     RectWithEndpoint local_clip_rect;
     69     float z;
     70     int specific_prim_address;
     71     int transform_id;
     72     int picture_task_address;
     73     ivec4 user_data;
     74 };
     75 
     76 PrimitiveHeader fetch_prim_header(int index) {
     77     PrimitiveHeader ph;
     78 
     79     ivec2 uv_f = get_fetch_uv(index, VECS_PER_PRIM_HEADER_F);
     80     vec4 local_rect = TEXEL_FETCH(sPrimitiveHeadersF, uv_f, 0, ivec2(0, 0));
     81     vec4 local_clip_rect = TEXEL_FETCH(sPrimitiveHeadersF, uv_f, 0, ivec2(1, 0));
     82     ph.local_rect = RectWithEndpoint(local_rect.xy, local_rect.zw);
     83     ph.local_clip_rect = RectWithEndpoint(local_clip_rect.xy, local_clip_rect.zw);
     84 
     85     ivec2 uv_i = get_fetch_uv(index, VECS_PER_PRIM_HEADER_I);
     86     ivec4 data0 = TEXEL_FETCH(sPrimitiveHeadersI, uv_i, 0, ivec2(0, 0));
     87     ivec4 data1 = TEXEL_FETCH(sPrimitiveHeadersI, uv_i, 0, ivec2(1, 0));
     88     ph.z = float(data0.x);
     89     ph.specific_prim_address = data0.y;
     90     ph.transform_id = data0.z;
     91     ph.picture_task_address = data0.w;
     92     ph.user_data = data1;
     93 
     94     return ph;
     95 }
     96 
     97 struct VertexInfo {
     98     vec2 local_pos;
     99     vec4 world_pos;
    100 };
    101 
    102 VertexInfo write_vertex(vec2 local_pos,
    103                         RectWithEndpoint local_clip_rect,
    104                         float z,
    105                         Transform transform,
    106                         PictureTask task) {
    107     // Clamp to the two local clip rects.
    108     vec2 clamped_local_pos = rect_clamp(local_clip_rect, local_pos);
    109 
    110     // Transform the current vertex to world space.
    111     vec4 world_pos = transform.m * vec4(clamped_local_pos, 0.0, 1.0);
    112 
    113     // Convert the world positions to device pixel space.
    114     vec2 device_pos = world_pos.xy * task.device_pixel_scale;
    115 
    116     // Apply offsets for the render task to get correct screen location.
    117     vec2 final_offset = -task.content_origin + task.task_rect.p0;
    118 
    119     gl_Position = uTransform * vec4(device_pos + final_offset * world_pos.w, z * world_pos.w, world_pos.w);
    120 
    121     VertexInfo vi = VertexInfo(
    122         clamped_local_pos,
    123         world_pos
    124     );
    125 
    126     return vi;
    127 }
    128 
    129 RectWithEndpoint clip_and_init_antialiasing(RectWithEndpoint segment_rect,
    130                                             RectWithEndpoint prim_rect,
    131                                             RectWithEndpoint clip_rect,
    132                                             int edge_flags,
    133                                             float z,
    134                                             Transform transform,
    135                                             PictureTask task) {
    136 #ifdef SWGL_ANTIALIAS
    137     // Check if the bounds are smaller than the unmodified segment rect. If so,
    138     // it is safe to enable AA on those edges.
    139     bvec4 clipped = bvec4(greaterThan(clip_rect.p0, segment_rect.p0),
    140                           lessThan(clip_rect.p1, segment_rect.p1));
    141     swgl_antiAlias(edge_flags | (clipped.x ? 1 : 0) | (clipped.y ? 2 : 0) |
    142                    (clipped.z ? 4 : 0) | (clipped.w ? 8 : 0));
    143 #endif
    144 
    145     segment_rect.p0 = clamp(segment_rect.p0, clip_rect.p0, clip_rect.p1);
    146     segment_rect.p1 = clamp(segment_rect.p1, clip_rect.p0, clip_rect.p1);
    147 
    148 #ifndef SWGL_ANTIALIAS
    149     prim_rect.p0 = clamp(prim_rect.p0, clip_rect.p0, clip_rect.p1);
    150     prim_rect.p1 = clamp(prim_rect.p1, clip_rect.p0, clip_rect.p1);
    151 
    152     // Select between the segment and prim edges based on edge mask.
    153     // We must perform the bitwise-and for each component individually, as a
    154     // vector bitwise-and followed by conversion to bvec4 causes shader
    155     // compilation crashes on some Adreno devices. See bug 1715746.
    156     bvec4 clip_edge_mask = bvec4(bool(edge_flags & 1), bool(edge_flags & 2), bool(edge_flags & 4), bool(edge_flags & 8));
    157     rectangle_aa_vertex(mix(
    158         vec4(vec2(-1e16), vec2(1e16)),
    159         vec4(segment_rect.p0, segment_rect.p1),
    160         clip_edge_mask
    161     ));
    162 
    163     // As this is a transform shader, extrude by 2 (local space) pixels
    164     // in each direction. This gives enough space around the edge to
    165     // apply distance anti-aliasing. Technically, it:
    166     // (a) slightly over-estimates the number of required pixels in the simple case.
    167     // (b) might not provide enough edge in edge case perspective projections.
    168     // However, it's fast and simple. If / when we ever run into issues, we
    169     // can do some math on the projection matrix to work out a variable
    170     // amount to extrude.
    171 
    172     // Only extrude along edges where we are going to apply AA.
    173     float extrude_amount = 2.0;
    174     vec4 extrude_distance = mix(vec4(0.0), vec4(extrude_amount), clip_edge_mask);
    175     segment_rect.p0 -= extrude_distance.xy;
    176     segment_rect.p1 += extrude_distance.zw;
    177 #endif
    178 
    179     return segment_rect;
    180 }
    181 
    182 void write_clip(vec4 world_pos, ClipArea area, PictureTask task) {
    183 #ifdef SWGL_CLIP_MASK
    184     swgl_clipMask(
    185         sClipMask,
    186         (task.task_rect.p0 - task.content_origin) - (area.task_rect.p0 - area.screen_origin),
    187         area.task_rect.p0,
    188         rect_size(area.task_rect)
    189     );
    190 #else
    191     vec2 uv = world_pos.xy * area.device_pixel_scale +
    192         world_pos.w * (area.task_rect.p0 - area.screen_origin);
    193     vClipMaskUvBounds = vec4(
    194         area.task_rect.p0,
    195         area.task_rect.p1
    196     );
    197     vClipMaskUv = uv;
    198 #endif
    199 }
    200 
    201 // Read the exta image data containing the homogeneous screen space coordinates
    202 // of the corners, interpolate between them, and return real screen space UV.
    203 vec2 get_image_quad_uv(int address, vec2 f) {
    204     ImageSourceExtra extra_data = fetch_image_source_extra(address);
    205     vec4 x = mix(extra_data.st_tl, extra_data.st_tr, f.x);
    206     vec4 y = mix(extra_data.st_bl, extra_data.st_br, f.x);
    207     vec4 z = mix(x, y, f.y);
    208     return z.xy / z.w;
    209 }
    210 #endif //WR_VERTEX_SHADER
    211 
    212 #ifdef WR_FRAGMENT_SHADER
    213 
    214 struct Fragment {
    215     vec4 color;
    216 #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
    217     vec4 blend;
    218 #endif
    219 };
    220 
    221 float do_clip() {
    222 #ifdef SWGL_CLIP_MASK
    223     // SWGL relies on builtin clip-mask support to do this more efficiently,
    224     // so no clipping is required here.
    225     return 1.0;
    226 #else
    227     // check for the dummy bounds, which are given to the opaque objects
    228     if (vClipMaskUvBounds.xy == vClipMaskUvBounds.zw) {
    229         return 1.0;
    230     }
    231     // anything outside of the mask is considered transparent
    232     //Note: we assume gl_FragCoord.w == interpolated(1 / vClipMaskUv.w)
    233     vec2 mask_uv = vClipMaskUv * gl_FragCoord.w;
    234     bvec2 left = lessThanEqual(vClipMaskUvBounds.xy, mask_uv); // inclusive
    235     bvec2 right = greaterThan(vClipMaskUvBounds.zw, mask_uv); // non-inclusive
    236     // bail out if the pixel is outside the valid bounds
    237     if (!all(bvec4(left, right))) {
    238         return 0.0;
    239     }
    240     // finally, the slow path - fetch the mask value from an image
    241     return texelFetch(sClipMask, ivec2(mask_uv), 0).r;
    242 #endif
    243 }
    244 
    245 #endif //WR_FRAGMENT_SHADER