Bug 1594128 - Add brush_blend to the multi-brush infrastructure. r=gw
authorNicolas Silva <nsilva@mozilla.com>
Wed, 27 Nov 2019 13:22:49 +0000
changeset 504189 dc267111d1744e222a971558d04b36ed22accd14
parent 504188 d4103eb1e6c5a951caa462814814933546c9c3d1
child 504190 7a8c9a2678763b6bbfa7652a986deb0f40feae59
push id36858
push usercbrindusan@mozilla.com
push dateThu, 28 Nov 2019 16:06:38 +0000
treeherdermozilla-central@6a3ca2b832f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1594128
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1594128 - Add brush_blend to the multi-brush infrastructure. r=gw Differential Revision: https://phabricator.services.mozilla.com/D53993
gfx/wr/webrender/res/brush.glsl
gfx/wr/webrender/res/brush_blend.glsl
gfx/wr/webrender/res/brush_multi.glsl
--- a/gfx/wr/webrender/res/brush.glsl
+++ b/gfx/wr/webrender/res/brush.glsl
@@ -64,16 +64,19 @@ flat varying int v_brush_kind;
 // A few varying slots for the brushes to use.
 // Using these instead of adding dedicated varyings avoids using a high
 // number of varyings in the multi-brush shader.
 flat varying vec4 flat_varying_vec4_0;
 flat varying vec4 flat_varying_vec4_1;
 flat varying vec4 flat_varying_vec4_2;
 flat varying vec4 flat_varying_vec4_3;
 flat varying vec4 flat_varying_vec4_4;
+
+flat varying ivec4 flat_varying_ivec4_0;
+
 varying vec4 varying_vec4_0;
 varying vec4 varying_vec4_1;
 
 #ifdef WR_VERTEX_SHADER
 
 #define FWD_DECLARE_VS_FUNCTION(name)   \
 void name(                              \
     VertexInfo vi,                      \
@@ -211,16 +214,22 @@ void main(void) {
             break;
         #endif
 
         #ifdef WR_FEATURE_SOLID_BRUSH
         case BRUSH_KIND_SOLID:
             solid_brush_vs(BRUSH_VS_PARAMS);
             break;
         #endif
+
+        #ifdef WR_FEATURE_BLEND_BRUSH
+        case BRUSH_KIND_BLEND:
+            blend_brush_vs(BRUSH_VS_PARAMS);
+            break;
+        #endif
     }
 
 #else
     WR_BRUSH_VS_FUNCTION(BRUSH_VS_PARAMS);
 #endif
 
 }
 
@@ -260,16 +269,22 @@ void main(void) {
         }
 #endif
 #ifdef WR_FEATURE_SOLID_BRUSH
         case BRUSH_KIND_SOLID: {
             frag = solid_brush_fs();
             break;
         }
 #endif
+#ifdef WR_FEATURE_BLEND_BRUSH
+        case BRUSH_KIND_BLEND: {
+            frag = blend_brush_fs();
+            break;
+        }
+#endif
     }
 #else
     frag = WR_BRUSH_FS_FUNCTION();
 #endif
 
 
 #ifdef WR_FEATURE_ALPHA_PASS
     // Apply the clip mask
--- a/gfx/wr/webrender/res/brush_blend.glsl
+++ b/gfx/wr/webrender/res/brush_blend.glsl
@@ -12,29 +12,38 @@
 #define COMPONENT_TRANSFER_TABLE 1
 #define COMPONENT_TRANSFER_DISCRETE 2
 #define COMPONENT_TRANSFER_LINEAR 3
 #define COMPONENT_TRANSFER_GAMMA 4
 
 #include shared,prim_shared,brush
 
 // Interpolated UV coordinates to sample.
-varying vec2 vUv;
-varying vec2 vLocalPos;
+#define V_UV                varying_vec4_0.zw
+#define V_LOCAL_POS         varying_vec4_0.xy
+
+#define V_FLOOD_COLOR       flat_varying_vec4_1
+
+// Normalized bounds of the source image in the texture.
+#define V_UV_BOUNDS         flat_varying_vec4_2
+
+#define V_COLOR_OFFSET      flat_varying_vec4_3.xyz
+#define V_AMOUNT            flat_varying_vec4_3.w
 
-// X = layer index to sample, Y = flag to allow perspective interpolation of UV.
-flat varying vec2 vLayerAndPerspective;
-flat varying float vAmount;
-flat varying int vOp;
+// Layer index to sample.
+#define V_LAYER             flat_varying_vec4_4.x
+// Flag to allow perspective interpolation of UV.
+#define V_PERSPECTIVE       flat_varying_vec4_4.y
+
+#define V_OP                flat_varying_ivec4_0.x
+#define V_TABLE_ADDRESS     flat_varying_ivec4_0.y
+
 flat varying mat3 vColorMat;
-flat varying vec3 vColorOffset;
-flat varying vec4 vUvClipBounds;
-flat varying int vTableAddress;
+
 flat varying int vFuncs[4];
-flat varying vec4 vFloodColor;
 
 #ifdef WR_VERTEX_SHADER
 
 void blend_brush_vs(
     VertexInfo vi,
     int prim_address,
     RectWithSize local_rect,
     RectWithSize segment_rect,
@@ -50,105 +59,109 @@ void blend_brush_vs(
     vec2 uv1 = res.uv_rect.p1;
 
     vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
     vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
     f = get_image_quad_uv(prim_user_data.x, f);
     vec2 uv = mix(uv0, uv1, f);
     float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;
 
-    vUv = uv / texture_size * mix(vi.world_pos.w, 1.0, perspective_interpolate);
-    vLayerAndPerspective = vec2(res.layer, perspective_interpolate);
-    vUvClipBounds = vec4(uv0, uv1) / texture_size.xyxy;
-    vLocalPos = vi.local_pos;
+    V_UV = uv / texture_size * mix(vi.world_pos.w, 1.0, perspective_interpolate);
+    V_LAYER = res.layer;
+    V_PERSPECTIVE = perspective_interpolate;
+
+    // TODO: The image shader treats this differently: deflate the rect by half a pixel on each side and
+    // clamp the uv in the frame shader. Does it make sense to do the same here?
+    V_UV_BOUNDS = vec4(uv0, uv1) / texture_size.xyxy;
+    V_LOCAL_POS = vi.local_pos;
 
     float lumR = 0.2126;
     float lumG = 0.7152;
     float lumB = 0.0722;
     float oneMinusLumR = 1.0 - lumR;
     float oneMinusLumG = 1.0 - lumG;
     float oneMinusLumB = 1.0 - lumB;
 
     float amount = float(prim_user_data.z) / 65536.0;
     float invAmount = 1.0 - amount;
 
-    vOp = prim_user_data.y & 0xffff;
-    vAmount = amount;
+    V_OP = prim_user_data.y & 0xffff;
+    V_AMOUNT = amount;
 
     // This assignment is only used for component transfer filters but this
     // assignment has to be done here and not in the component transfer case
     // below because it doesn't get executed on Windows because of a suspected
     // miscompile of this shader on Windows. See
     // https://github.com/servo/webrender/wiki/Driver-issues#bug-1505871---assignment-to-varying-flat-arrays-inside-switch-statement-of-vertex-shader-suspected-miscompile-on-windows
     // default: just to satisfy angle_shader_validation.rs which needs one
     // default: for every switch, even in comments.
     vFuncs[0] = (prim_user_data.y >> 28) & 0xf; // R
     vFuncs[1] = (prim_user_data.y >> 24) & 0xf; // G
     vFuncs[2] = (prim_user_data.y >> 20) & 0xf; // B
     vFuncs[3] = (prim_user_data.y >> 16) & 0xf; // A
 
-    switch (vOp) {
+    switch (V_OP) {
         case 2: {
             // Grayscale
             vColorMat = mat3(
                 vec3(lumR + oneMinusLumR * invAmount, lumR - lumR * invAmount, lumR - lumR * invAmount),
                 vec3(lumG - lumG * invAmount, lumG + oneMinusLumG * invAmount, lumG - lumG * invAmount),
                 vec3(lumB - lumB * invAmount, lumB - lumB * invAmount, lumB + oneMinusLumB * invAmount)
             );
-            vColorOffset = vec3(0.0);
+            V_COLOR_OFFSET = vec3(0.0);
             break;
         }
         case 3: {
             // HueRotate
             float c = cos(amount);
             float s = sin(amount);
             vColorMat = mat3(
                 vec3(lumR + oneMinusLumR * c - lumR * s, lumR - lumR * c + 0.143 * s, lumR - lumR * c - oneMinusLumR * s),
                 vec3(lumG - lumG * c - lumG * s, lumG + oneMinusLumG * c + 0.140 * s, lumG - lumG * c + lumG * s),
                 vec3(lumB - lumB * c + oneMinusLumB * s, lumB - lumB * c - 0.283 * s, lumB + oneMinusLumB * c + lumB * s)
             );
-            vColorOffset = vec3(0.0);
+            V_COLOR_OFFSET = vec3(0.0);
             break;
         }
         case 5: {
             // Saturate
             vColorMat = mat3(
                 vec3(invAmount * lumR + amount, invAmount * lumR, invAmount * lumR),
                 vec3(invAmount * lumG, invAmount * lumG + amount, invAmount * lumG),
                 vec3(invAmount * lumB, invAmount * lumB, invAmount * lumB + amount)
             );
-            vColorOffset = vec3(0.0);
+            V_COLOR_OFFSET = vec3(0.0);
             break;
         }
         case 6: {
             // Sepia
             vColorMat = mat3(
                 vec3(0.393 + 0.607 * invAmount, 0.349 - 0.349 * invAmount, 0.272 - 0.272 * invAmount),
                 vec3(0.769 - 0.769 * invAmount, 0.686 + 0.314 * invAmount, 0.534 - 0.534 * invAmount),
                 vec3(0.189 - 0.189 * invAmount, 0.168 - 0.168 * invAmount, 0.131 + 0.869 * invAmount)
             );
-            vColorOffset = vec3(0.0);
+            V_COLOR_OFFSET = vec3(0.0);
             break;
         }
         case 10: {
             // Color Matrix
             vec4 mat_data[3] = fetch_from_gpu_cache_3(prim_user_data.z);
             vec4 offset_data = fetch_from_gpu_cache_1(prim_user_data.z + 4);
             vColorMat = mat3(mat_data[0].xyz, mat_data[1].xyz, mat_data[2].xyz);
-            vColorOffset = offset_data.rgb;
+            V_COLOR_OFFSET = offset_data.rgb;
             break;
         }
         case 13: {
             // Component Transfer
-            vTableAddress = prim_user_data.z;
+            V_TABLE_ADDRESS = prim_user_data.z;
             break;
         }
         case 14: {
             // Flood
-            vFloodColor = fetch_from_gpu_cache_1(prim_user_data.z);
+            V_FLOOD_COLOR = fetch_from_gpu_cache_1(prim_user_data.z);
             break;
         }
         default: break;
     }
 }
 #endif
 
 #ifdef WR_FRAGMENT_SHADER
@@ -206,69 +219,69 @@ vec4 ComponentTransfer(vec4 colora) {
     for (int i = 0; i < 4; i++) {
         switch (vFuncs[i]) {
             case COMPONENT_TRANSFER_IDENTITY:
                 break;
             case COMPONENT_TRANSFER_TABLE:
             case COMPONENT_TRANSFER_DISCRETE: {
                 // fetch value from lookup table
                 k = int(floor(colora[i]*255.0));
-                texel = fetch_from_gpu_cache_1(vTableAddress + offset + k/4);
+                texel = fetch_from_gpu_cache_1(V_TABLE_ADDRESS + offset + k/4);
                 colora[i] = clamp(texel[k % 4], 0.0, 1.0);
                 // offset plus 256/4 blocks
                 offset = offset + 64;
                 break;
             }
             case COMPONENT_TRANSFER_LINEAR: {
                 // fetch the two values for use in the linear equation
-                texel = fetch_from_gpu_cache_1(vTableAddress + offset);
+                texel = fetch_from_gpu_cache_1(V_TABLE_ADDRESS + offset);
                 colora[i] = clamp(texel[0] * colora[i] + texel[1], 0.0, 1.0);
                 // offset plus 1 block
                 offset = offset + 1;
                 break;
             }
             case COMPONENT_TRANSFER_GAMMA: {
                 // fetch the three values for use in the gamma equation
-                texel = fetch_from_gpu_cache_1(vTableAddress + offset);
+                texel = fetch_from_gpu_cache_1(V_TABLE_ADDRESS + offset);
                 colora[i] = clamp(texel[0] * pow(colora[i], texel[1]) + texel[2], 0.0, 1.0);
                 // offset plus 1 block
                 offset = offset + 1;
                 break;
             }
             default:
                 // shouldn't happen
                 break;
         }
     }
     return colora;
 }
 
 Fragment blend_brush_fs() {
-    float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
-    vec2 uv = vUv * perspective_divisor;
-    vec4 Cs = texture(sColor0, vec3(uv, vLayerAndPerspective.x));
+    float perspective_divisor = mix(gl_FragCoord.w, 1.0, V_PERSPECTIVE);
+    vec2 uv = V_UV * perspective_divisor;
+    vec4 Cs = texture(sColor0, vec3(uv, V_LAYER));
 
     // Un-premultiply the input.
     float alpha = Cs.a;
     vec3 color = alpha != 0.0 ? Cs.rgb / alpha : Cs.rgb;
 
-    switch (vOp) {
+    switch (V_OP) {
         case 0:
             break;
         case 1:
-            color = Contrast(color, vAmount);
+            color = Contrast(color, V_AMOUNT);
             break;
         case 4:
-            color = Invert(color, vAmount);
+            color = Invert(color, V_AMOUNT);
             break;
         case 7:
-            color = Brightness(color, vAmount);
+            color = Brightness(color, V_AMOUNT);
             break;
         case 8: // Opacity
-            alpha *= vAmount;
+            alpha *= V_AMOUNT;
             break;
         case 11:
             color = SrgbToLinear(color);
             break;
         case 12:
             color = LinearToSrgb(color);
             break;
         case 13: {
@@ -276,24 +289,36 @@ Fragment blend_brush_fs() {
             // Get the unpremultiplied color with alpha.
             vec4 colora = vec4(color, alpha);
             colora = ComponentTransfer(colora);
             color = colora.rgb;
             alpha = colora.a;
             break;
         }
         case 14: // Flood
-            color = vFloodColor.rgb;
-            alpha = vFloodColor.a;
+            color = V_FLOOD_COLOR.rgb;
+            alpha = V_FLOOD_COLOR.a;
             break;
         default:
-            color = vColorMat * color + vColorOffset;
+            color = vColorMat * color + V_COLOR_OFFSET;
     }
 
     // Fail-safe to ensure that we don't sample outside the rendered
     // portion of a blend source.
-    alpha *= min(point_inside_rect(uv, vUvClipBounds.xy, vUvClipBounds.zw),
-                 init_transform_fs(vLocalPos));
+    alpha *= min(point_inside_rect(uv, V_UV_BOUNDS.xy, V_UV_BOUNDS.zw),
+                 init_transform_fs(V_LOCAL_POS));
 
     // Pre-multiply the alpha into the output value.
     return Fragment(alpha * vec4(color, 1.0));
 }
 #endif
+
+// Undef macro names that could be re-defined by other shaders.
+#undef V_UV
+#undef V_LOCAL_POS
+#undef V_FLOOD_COLOR
+#undef V_UV_BOUNDS
+#undef V_COLOR_OFFSET
+#undef V_AMOUNT
+#undef V_LAYER
+#undef V_PERSPECTIVE
+#undef V_OP
+#undef V_TABLE_ADDRESS
--- a/gfx/wr/webrender/res/brush_multi.glsl
+++ b/gfx/wr/webrender/res/brush_multi.glsl
@@ -15,26 +15,40 @@ int vecs_per_brush(int brush_kind);
 #undef VECS_PER_SPECIFIC_BRUSH
 #undef WR_BRUSH_VS_FUNCTION
 #undef WR_BRUSH_FS_FUNCTION
 
 #ifdef WR_FEATURE_SOLID_BRUSH
 #include brush_solid
 #endif
 
+#undef VECS_PER_SPECIFIC_BRUSH
+#undef WR_BRUSH_VS_FUNCTION
+#undef WR_BRUSH_FS_FUNCTION
+
+#ifdef WR_FEATURE_BLEND_BRUSH
+#include brush_blend
+#endif
+
 int vecs_per_brush(int brush_kind) {
     int result;
     switch (brush_kind) {
         #ifdef WR_FEATURE_IMAGE_BRUSH
         case BRUSH_KIND_IMAGE:
             result = VECS_PER_IMAGE_BRUSH;
             break;
         #endif
 
         #ifdef WR_FEATURE_IMAGE_BRUSH
         case BRUSH_KIND_SOLID:
             result = VECS_PER_SOLID_BRUSH;
             break;
         #endif
+
+        #ifdef WR_FEATURE_BLEND_BRUSH
+        case BRUSH_KIND_BLEND:
+            result = VECS_PER_BLEND_BRUSH;
+            break;
+        #endif
     }
 
     return result;
 }