tor-browser

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

composite.glsl (9195B)


      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 // Composite a picture cache tile into the framebuffer.
      6 
      7 // This shader must remain compatible with ESSL 1, at least for the
      8 // WR_FEATURE_TEXTURE_EXTERNAL_ESSL1 feature, so that it can be used to render
      9 // video on GLES devices without GL_OES_EGL_image_external_essl3 support.
     10 // This means we cannot use textureSize(), int inputs/outputs, etc.
     11 
     12 #include shared
     13 
     14 #ifdef WR_FEATURE_YUV
     15 #include yuv
     16 #endif
     17 
     18 #ifndef WR_FEATURE_FAST_PATH
     19 // Parameters for compositor clip
     20 varying highp vec2 vNormalizedWorldPos;
     21 flat varying highp vec2 vRoundedClipParams;
     22 flat varying highp vec4 vRoundedClipRadii;
     23 #endif
     24 
     25 #ifdef WR_FEATURE_YUV
     26 flat varying YUV_PRECISION vec3 vYcbcrBias;
     27 flat varying YUV_PRECISION mat3 vRgbFromDebiasedYcbcr;
     28 // YUV format. Packed in to vector to avoid bug 1630356.
     29 flat varying mediump ivec2 vYuvFormat;
     30 
     31 #ifdef SWGL_DRAW_SPAN
     32 flat varying mediump int vRescaleFactor;
     33 #endif
     34 varying highp vec2 vUV_y;
     35 varying highp vec2 vUV_u;
     36 varying highp vec2 vUV_v;
     37 flat varying highp vec4 vUVBounds_y;
     38 flat varying highp vec4 vUVBounds_u;
     39 flat varying highp vec4 vUVBounds_v;
     40 #else
     41 varying highp vec2 vUv;
     42 #ifndef WR_FEATURE_FAST_PATH
     43 flat varying mediump vec4 vColor;
     44 flat varying highp vec4 vUVBounds;
     45 #endif
     46 #ifdef WR_FEATURE_TEXTURE_EXTERNAL_ESSL1
     47 uniform mediump vec2 uTextureSize;
     48 #endif
     49 #endif
     50 
     51 #ifdef WR_VERTEX_SHADER
     52 // CPU side data is in CompositeInstance (gpu_types.rs) and is
     53 // converted to GPU data using desc::COMPOSITE (renderer.rs) by
     54 // filling vaos.composite_vao with VertexArrayKind::Composite.
     55 PER_INSTANCE attribute vec4 aDeviceRect;
     56 PER_INSTANCE attribute vec4 aDeviceClipRect;
     57 PER_INSTANCE attribute vec4 aColor;
     58 PER_INSTANCE attribute vec4 aParams;
     59 PER_INSTANCE attribute vec2 aFlip;
     60 
     61 #ifndef WR_FEATURE_FAST_PATH
     62 PER_INSTANCE attribute vec4 aDeviceRoundedClipRect;
     63 PER_INSTANCE attribute vec4 aDeviceRoundedClipRadii;
     64 #endif
     65 
     66 #ifdef WR_FEATURE_YUV
     67 // YUV treats these as a UV clip rect (clamp)
     68 PER_INSTANCE attribute vec4 aUvRect0;
     69 PER_INSTANCE attribute vec4 aUvRect1;
     70 PER_INSTANCE attribute vec4 aUvRect2;
     71 #else
     72 PER_INSTANCE attribute vec4 aUvRect0;
     73 #endif
     74 
     75 #ifdef WR_FEATURE_YUV
     76 YuvPrimitive fetch_yuv_primitive() {
     77     // From ExternalSurfaceDependency::Yuv:
     78     int color_space = int(aParams.y);
     79     int yuv_format = int(aParams.z);
     80     int channel_bit_depth = int(aParams.w);
     81     return YuvPrimitive(channel_bit_depth, color_space, yuv_format);
     82 }
     83 #endif
     84 
     85 void main(void) {
     86     // Flip device rect if required
     87     vec4 device_rect = mix(aDeviceRect.xyzw, aDeviceRect.zwxy, aFlip.xyxy);
     88 
     89     // Get world position
     90     vec2 world_pos = mix(device_rect.xy, device_rect.zw, aPosition.xy);
     91 
     92     // Clip the position to the world space clip rect
     93     vec2 clipped_world_pos = clamp(world_pos, aDeviceClipRect.xy, aDeviceClipRect.zw);
     94 
     95 #ifndef WR_FEATURE_FAST_PATH
     96     vec2 half_clip_box_size = 0.5 * (aDeviceRoundedClipRect.zw - aDeviceRoundedClipRect.xy);
     97     vNormalizedWorldPos = aDeviceRoundedClipRect.xy + half_clip_box_size - clipped_world_pos;
     98     vRoundedClipParams = half_clip_box_size;
     99     vRoundedClipRadii = aDeviceRoundedClipRadii;
    100 #endif
    101 
    102     // Derive the normalized UV from the clipped vertex position
    103     vec2 uv = (clipped_world_pos - device_rect.xy) / (device_rect.zw - device_rect.xy);
    104 
    105 #ifdef WR_FEATURE_YUV
    106     YuvPrimitive prim = fetch_yuv_primitive();
    107 
    108 #ifdef SWGL_DRAW_SPAN
    109     // swgl_commitTextureLinearYUV needs to know the color space specifier and
    110     // also needs to know how many bits of scaling are required to normalize
    111     // HDR textures. Note that MSB HDR formats don't need renormalization.
    112     vRescaleFactor = 0;
    113     if (prim.channel_bit_depth > 8 && prim.yuv_format != YUV_FORMAT_P010) {
    114         vRescaleFactor = 16 - prim.channel_bit_depth;
    115     }
    116 #endif
    117 
    118     YuvColorMatrixInfo mat_info = get_rgb_from_ycbcr_info(prim);
    119     vYcbcrBias = mat_info.ycbcr_bias;
    120     vRgbFromDebiasedYcbcr = mat_info.rgb_from_debiased_ycbrc;
    121 
    122     vYuvFormat.x = prim.yuv_format;
    123 
    124     write_uv_rect(
    125         aUvRect0.xy,
    126         aUvRect0.zw,
    127         uv,
    128         TEX_SIZE_YUV(sColor0),
    129         vUV_y,
    130         vUVBounds_y
    131     );
    132     write_uv_rect(
    133         aUvRect1.xy,
    134         aUvRect1.zw,
    135         uv,
    136         TEX_SIZE_YUV(sColor1),
    137         vUV_u,
    138         vUVBounds_u
    139     );
    140     write_uv_rect(
    141         aUvRect2.xy,
    142         aUvRect2.zw,
    143         uv,
    144         TEX_SIZE_YUV(sColor2),
    145         vUV_v,
    146         vUVBounds_v
    147     );
    148 #else
    149     uv = mix(aUvRect0.xy, aUvRect0.zw, uv);
    150     // The uvs may be inverted, so use the min and max for the bounds
    151     vec4 uvBounds = vec4(min(aUvRect0.xy, aUvRect0.zw), max(aUvRect0.xy, aUvRect0.zw));
    152     if (int(aParams.y) == UV_TYPE_UNNORMALIZED) {
    153         // using an atlas, so UVs are in pixels, and need to be
    154         // normalized and clamped.
    155 #if defined(WR_FEATURE_TEXTURE_RECT)
    156         vec2 texture_size = vec2(1.0, 1.0);
    157 #elif defined(WR_FEATURE_TEXTURE_EXTERNAL_ESSL1)
    158         vec2 texture_size = uTextureSize;
    159 #else
    160         vec2 texture_size = vec2(TEX_SIZE(sColor0));
    161 #endif
    162         uvBounds += vec4(0.5, 0.5, -0.5, -0.5);
    163     #ifndef WR_FEATURE_TEXTURE_RECT
    164         uv /= texture_size;
    165         uvBounds /= texture_size.xyxy;
    166     #endif
    167     }
    168 
    169     vUv = uv;
    170 #ifndef WR_FEATURE_FAST_PATH
    171     vUVBounds = uvBounds;
    172     // Pass through color
    173     vColor = aColor;
    174 #endif
    175 #endif
    176 
    177     gl_Position = uTransform * vec4(clipped_world_pos, 0.0, 1.0);
    178 }
    179 #endif
    180 
    181 #ifdef WR_FRAGMENT_SHADER
    182 
    183 #ifndef WR_FEATURE_FAST_PATH
    184 // See https://www.shadertoy.com/view/4llXD7
    185 // Notes:
    186 //  * pos is centered in the origin (so 0,0 is the center of the box).
    187 //  * The border radii must not be larger than half_box_size.
    188 float sd_round_box(in vec2 pos, in vec2 half_box_size, in vec4 radii) {
    189     radii.xy = (pos.x > 0.0) ? radii.xy : radii.zw;
    190     radii.x  = (pos.y > 0.0) ? radii.x  : radii.y;
    191     vec2 q = abs(pos) - half_box_size + radii.x;
    192     return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radii.x;
    193 }
    194 #endif
    195 
    196 void main(void) {
    197 #ifdef WR_FEATURE_YUV
    198     vec4 color = sample_yuv(
    199         vYuvFormat.x,
    200         vYcbcrBias,
    201         vRgbFromDebiasedYcbcr,
    202         vUV_y,
    203         vUV_u,
    204         vUV_v,
    205         vUVBounds_y,
    206         vUVBounds_u,
    207         vUVBounds_v
    208     );
    209 #else
    210     // The color is just the texture sample modulated by a supplied color.
    211     // In the fast path we avoid clamping the UV coordinates and modulating by the color.
    212 #ifdef WR_FEATURE_FAST_PATH
    213     vec2 uv = vUv;
    214 #else
    215     vec2 uv = clamp(vUv, vUVBounds.xy, vUVBounds.zw);
    216 #endif
    217     vec4 texel = TEX_SAMPLE(sColor0, uv);
    218 #ifdef WR_FEATURE_FAST_PATH
    219     vec4 color = texel;
    220 #else
    221     vec4 color = vColor * texel;
    222 #endif
    223 #endif
    224 
    225 // TODO(gw): Do we need to support this on ESSL1?
    226 #ifndef WR_FEATURE_TEXTURE_EXTERNAL_ESSL1
    227 #ifndef WR_FEATURE_FAST_PATH
    228     // Apply compositor clip
    229     float aa_range = compute_aa_range(vNormalizedWorldPos);
    230 
    231     float dist = sd_round_box(
    232         vNormalizedWorldPos,
    233         vRoundedClipParams,
    234         vRoundedClipRadii
    235     );
    236 
    237     // Compute AA for the given dist and range.
    238     float clip_alpha =  distance_aa(aa_range, dist);
    239 
    240     // Apply clip alpha
    241     color *= clip_alpha;
    242 #endif
    243 #endif
    244 
    245     write_output(color);
    246 }
    247 
    248 #ifdef SWGL_DRAW_SPAN
    249 void swgl_drawSpanRGBA8() {
    250 
    251 #ifndef WR_FEATURE_FAST_PATH
    252     // If there is per-fragment clipping to do, we need to bail
    253     // out of the span shader.
    254     if (any(greaterThan(vRoundedClipRadii, vec4(0.0)))) {
    255         return;
    256     }
    257 #endif      // WR_FEATURE_FAST_PATH
    258 
    259 #ifdef WR_FEATURE_YUV
    260     if (vYuvFormat.x == YUV_FORMAT_PLANAR) {
    261         swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y,
    262                                     sColor1, vUV_u, vUVBounds_u,
    263                                     sColor2, vUV_v, vUVBounds_v,
    264                                     vYcbcrBias,
    265                                     vRgbFromDebiasedYcbcr,
    266                                     vRescaleFactor);
    267     } else if (vYuvFormat.x == YUV_FORMAT_NV12 || vYuvFormat.x == YUV_FORMAT_P010) {
    268         swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y,
    269                                     sColor1, vUV_u, vUVBounds_u,
    270                                     vYcbcrBias,
    271                                     vRgbFromDebiasedYcbcr,
    272                                     vRescaleFactor);
    273     } else if (vYuvFormat.x == YUV_FORMAT_INTERLEAVED) {
    274         swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y,
    275                                     vYcbcrBias,
    276                                     vRgbFromDebiasedYcbcr,
    277                                     vRescaleFactor);
    278     }
    279 #else
    280 #ifdef WR_FEATURE_FAST_PATH
    281     vec4 color = vec4(1.0);
    282 #ifdef WR_FEATURE_TEXTURE_RECT
    283     vec4 uvBounds = vec4(vec2(0.0), vec2(textureSize(sColor0)));
    284 #else
    285     vec4 uvBounds = vec4(0.0, 0.0, 1.0, 1.0);
    286 #endif
    287 #else
    288     vec4 color = vColor;
    289     vec4 uvBounds = vUVBounds;
    290 #endif
    291 
    292     if (color != vec4(1.0)) {
    293         swgl_commitTextureColorRGBA8(sColor0, vUv, uvBounds, color);
    294     } else {
    295         swgl_commitTextureRGBA8(sColor0, vUv, uvBounds);
    296     }
    297 #endif
    298 }
    299 #endif      // SWGL_DRAW_SPAN
    300 
    301 #endif