Bug 1505871. Implementation of shaders. r=gw
authorTimothy Nikkel <tnikkel@gmail.com>
Tue, 26 Feb 2019 00:16:37 -0600
changeset 519013 1562b43107f242b18e342c8b7c9c76b9aa9fcf96
parent 519012 457a27c7b181799671e43b99becb2420d03cdf62
child 519014 55ba29bf61f031b82f94a76e18f2f769ac0b264e
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1505871
milestone67.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 1505871. Implementation of shaders. r=gw
gfx/wr/webrender/res/brush_blend.glsl
gfx/wr/webrender/res/gpu_cache.glsl
--- a/gfx/wr/webrender/res/brush_blend.glsl
+++ b/gfx/wr/webrender/res/brush_blend.glsl
@@ -1,26 +1,34 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #define VECS_PER_SPECIFIC_BRUSH 3
 
+#define COMPONENT_TRANSFER_IDENTITY 0
+#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;
 
 // 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;
 flat varying mat3 vColorMat;
 flat varying vec3 vColorOffset;
 flat varying vec4 vUvClipBounds;
+flat varying int vTableAddress;
+flat varying int vFuncs[4];
 
 #ifdef WR_VERTEX_SHADER
 
 void brush_vs(
     VertexInfo vi,
     int prim_address,
     RectWithSize local_rect,
     RectWithSize segment_rect,
@@ -50,17 +58,17 @@ void brush_vs(
     float lumB = 0.0722;
     float oneMinusLumR = 1.0 - lumR;
     float oneMinusLumG = 1.0 - lumG;
     float oneMinusLumB = 1.0 - lumB;
 
     float amount = float(user_data.z) / 65536.0;
     float invAmount = 1.0 - amount;
 
-    vOp = user_data.y;
+    vOp = user_data.y & 0xffff;
     vAmount = amount;
 
     switch (vOp) {
         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),
@@ -104,16 +112,25 @@ void brush_vs(
         case 10: {
             // Color Matrix
             vec4 mat_data[3] = fetch_from_gpu_cache_3(user_data.z);
             vec4 offset_data = fetch_from_gpu_cache_1(user_data.z + 4);
             vColorMat = mat3(mat_data[0].xyz, mat_data[1].xyz, mat_data[2].xyz);
             vColorOffset = offset_data.rgb;
             break;
         }
+        case 13: {
+            // Component Transfer
+            vTableAddress = user_data.z;
+            vFuncs[0] = (user_data.y >> 28) & 0xf; // R
+            vFuncs[1] = (user_data.y >> 24) & 0xf; // G
+            vFuncs[2] = (user_data.y >> 20) & 0xf; // B
+            vFuncs[3] = (user_data.y >> 16) & 0xf; // A
+            break;
+        }
         default: break;
     }
 }
 #endif
 
 #ifdef WR_FRAGMENT_SHADER
 vec3 Contrast(vec3 Cs, float amount) {
     return Cs.rgb * amount - 0.5 * amount + 0.5;
@@ -172,16 +189,68 @@ Fragment brush_fs() {
             alpha *= vAmount;
             break;
         case 11:
             color = SrgbToLinear(color);
             break;
         case 12:
             color = LinearToSrgb(color);
             break;
+        case 13: // Component Transfer
+            int offset = 0;
+            vec4 texel;
+            int k;
+
+            // We push a different amount of data to the gpu cache depending
+            // on the function type.
+            // Identity => 0 blocks
+            // Table/Discrete => 64 blocks (256 values)
+            // Linear => 1 block (2 values)
+            // Gamma => 1 block (3 values)
+            // We loop through the color components and increment the offset
+            // (for the next color component) into the gpu cache based on how
+            // many blocks that function type put into the gpu cache.
+            // Table/Discrete use a 256 entry look up table.
+            // Linear/Gamma are a simple calculation.
+            vec4 colora = alpha != 0.0 ? Cs / alpha : Cs;
+            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);
+                        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);
+                        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);
+                        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;
+                }
+            }
+            color = colora.rgb;
+            alpha = colora.a;
+            break;
         default:
             color = vColorMat * color + vColorOffset;
     }
 
     // Fail-safe to ensure that we don't sample outside the rendered
     // portion of a blend source.
     alpha *= point_inside_rect(uv, vUvClipBounds.xy, vUvClipBounds.zw);
 
--- a/gfx/wr/webrender/res/gpu_cache.glsl
+++ b/gfx/wr/webrender/res/gpu_cache.glsl
@@ -28,16 +28,25 @@ vec4[2] fetch_from_gpu_cache_2_direct(iv
 vec4[2] fetch_from_gpu_cache_2(int address) {
     ivec2 uv = get_gpu_cache_uv(address);
     return vec4[2](
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(0, 0)),
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(1, 0))
     );
 }
 
+vec4 fetch_from_gpu_cache_1_direct(ivec2 address) {
+    return texelFetch(sGpuCache, address, 0);
+}
+
+vec4 fetch_from_gpu_cache_1(int address) {
+    ivec2 uv = get_gpu_cache_uv(address);
+    return texelFetch(sGpuCache, uv, 0);
+}
+
 #ifdef WR_VERTEX_SHADER
 
 vec4[8] fetch_from_gpu_cache_8(int address) {
     ivec2 uv = get_gpu_cache_uv(address);
     return vec4[8](
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(0, 0)),
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(1, 0)),
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(2, 0)),
@@ -80,25 +89,16 @@ vec4[4] fetch_from_gpu_cache_4(int addre
     return vec4[4](
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(0, 0)),
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(1, 0)),
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(2, 0)),
         TEXEL_FETCH(sGpuCache, uv, 0, ivec2(3, 0))
     );
 }
 
-vec4 fetch_from_gpu_cache_1_direct(ivec2 address) {
-    return texelFetch(sGpuCache, address, 0);
-}
-
-vec4 fetch_from_gpu_cache_1(int address) {
-    ivec2 uv = get_gpu_cache_uv(address);
-    return texelFetch(sGpuCache, uv, 0);
-}
-
 //TODO: image resource is too specific for this module
 
 struct ImageResource {
     RectWithEndpoint uv_rect;
     float layer;
     vec3 user_data;
 };