Backed out 5 changesets (bug 1555483) for causing wrench bustages CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Wed, 10 Jul 2019 23:27:36 +0300
changeset 482271 27679131d486cb10ecb6337688db6e84cc8b48e4
parent 482270 1edf0457ac230fdbdb31fd621bb49c4188daa9fc
child 482272 6484c07ff83649914781ddc9cfb70e98466cdd7a
push id89666
push usernerli@mozilla.com
push dateWed, 10 Jul 2019 20:28:04 +0000
treeherderautoland@27679131d486 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1555483
milestone70.0a1
backs out8149efc1f8131d09db617e82c9e6fbde25cccd0c
917f800e4e43a0dc4799dd5893d4fa4b96454857
418839320ab5b103817da82d7582016c3cf8ccbe
134a51a0e03463d045ab71b79d251a91c70a8cd9
7c43dc769da78fe45d9caf3d5dbd0205f33aa156
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
Backed out 5 changesets (bug 1555483) for causing wrench bustages CLOSED TREE Backed out changeset 8149efc1f813 (bug 1555483) Backed out changeset 917f800e4e43 (bug 1555483) Backed out changeset 418839320ab5 (bug 1555483) Backed out changeset 134a51a0e034 (bug 1555483) Backed out changeset 7c43dc769da7 (bug 1555483)
gfx/webrender_bindings/src/bindings.rs
gfx/wr/examples/animation.rs
gfx/wr/webrender/res/cs_svg_filter.glsl
gfx/wr/webrender/src/batch.rs
gfx/wr/webrender/src/display_list_flattener.rs
gfx/wr/webrender/src/filterdata.rs
gfx/wr/webrender/src/gpu_types.rs
gfx/wr/webrender/src/picture.rs
gfx/wr/webrender/src/prim_store/mod.rs
gfx/wr/webrender/src/prim_store/picture.rs
gfx/wr/webrender/src/render_task.rs
gfx/wr/webrender/src/renderer.rs
gfx/wr/webrender/src/scene.rs
gfx/wr/webrender/src/shade.rs
gfx/wr/webrender/src/tiling.rs
gfx/wr/webrender/tests/angle_shader_validation.rs
gfx/wr/webrender_api/src/display_item.rs
gfx/wr/webrender_api/src/display_list.rs
gfx/wr/wrench/reftests/filters/filter-flood-ref.yaml
gfx/wr/wrench/reftests/filters/filter-flood.yaml
gfx/wr/wrench/reftests/filters/reftest.list
gfx/wr/wrench/reftests/filters/svg-filter-blend-ref.yaml
gfx/wr/wrench/reftests/filters/svg-filter-blend.yaml
gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.png
gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.yaml
gfx/wr/wrench/reftests/filters/svg-filter-blur.yaml
gfx/wr/wrench/reftests/filters/svg-filter-color-matrix.yaml
gfx/wr/wrench/reftests/filters/svg-filter-component-transfer.yaml
gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.png
gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.yaml
gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.png
gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.yaml
gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate-ref.yaml
gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate.yaml
gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.png
gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.yaml
gfx/wr/wrench/reftests/filters/svg-filter-flood-ref.yaml
gfx/wr/wrench/reftests/filters/svg-filter-flood.yaml
gfx/wr/wrench/reftests/filters/svg-srgb-to-linear.yaml
gfx/wr/wrench/reftests/mask/reftest.list
gfx/wr/wrench/src/yaml_frame_reader.rs
gfx/wr/wrench/src/yaml_frame_writer.rs
gfx/wr/wrench/src/yaml_helper.rs
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -2184,17 +2184,16 @@ pub extern "C" fn wr_dp_push_stacking_co
          .push_stacking_context(bounds.origin,
                                 wr_spatial_id,
                                 params.is_backface_visible,
                                 wr_clip_id,
                                 params.transform_style,
                                 params.mix_blend_mode,
                                 &filters,
                                 &r_filter_datas,
-                                &[],
                                 glyph_raster_space,
                                 params.cache_tiles);
 
     result
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState,
--- a/gfx/wr/examples/animation.rs
+++ b/gfx/wr/examples/animation.rs
@@ -66,17 +66,16 @@ impl App {
         );
 
         builder.push_simple_stacking_context_with_filters(
             LayoutPoint::zero(),
             spatial_id,
             true,
             &filters,
             &[],
-            &[]
         );
 
         let space_and_clip = SpaceAndClipInfo {
             spatial_id,
             clip_id: ClipId::root(pipeline_id),
         };
         let clip_bounds = LayoutRect::new(LayoutPoint::zero(), bounds.size);
         let complex_clip = ComplexClipRegion {
deleted file mode 100644
--- a/gfx/wr/webrender/res/cs_svg_filter.glsl
+++ /dev/null
@@ -1,534 +0,0 @@
-/* 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/. */
-
-#include shared,prim_shared
-
-varying vec3 vInput1Uv;
-varying vec3 vInput2Uv;
-flat varying vec4 vInput1UvRect;
-flat varying vec4 vInput2UvRect;
-flat varying int vFilterInputCount;
-flat varying int vFilterKind;
-flat varying ivec4 vData;
-flat varying vec4 vFilterData0;
-flat varying vec4 vFilterData1;
-flat varying float vFloat0;
-flat varying mat3 vColorMat;
-flat varying int vFuncs[4];
-
-#define FILTER_BLEND                0
-#define FILTER_FLOOD                1
-#define FILTER_LINEAR_TO_SRGB       2
-#define FILTER_SRGB_TO_LINEAR       3
-#define FILTER_OPACITY              4
-#define FILTER_COLOR_MATRIX         5
-#define FILTER_DROP_SHADOW          6
-#define FILTER_OFFSET               7
-#define FILTER_COMPONENT_TRANSFER   8
-#define FILTER_IDENTITY             9
-
-#ifdef WR_VERTEX_SHADER
-
-in int aFilterRenderTaskAddress;
-in int aFilterInput1TaskAddress;
-in int aFilterInput2TaskAddress;
-in int aFilterKind;
-in int aFilterInputCount;
-in int aFilterGenericInt;
-in ivec2 aFilterExtraDataAddress;
-
-struct FilterTask {
-    RenderTaskCommonData common_data;
-    vec3 user_data;
-};
-
-FilterTask fetch_filter_task(int address) {
-    RenderTaskData task_data = fetch_render_task_data(address);
-
-    FilterTask task = FilterTask(
-        task_data.common_data,
-        task_data.user_data.xyz
-    );
-
-    return task;
-}
-
-vec4 compute_uv_rect(RenderTaskCommonData task, vec2 texture_size) {
-    RectWithSize task_rect = task.task_rect;
-
-    vec4 uvRect = vec4(task_rect.p0 + vec2(0.5),
-                       task_rect.p0 + task_rect.size - vec2(0.5));
-    uvRect /= texture_size.xyxy;
-    return uvRect;
-}
-
-vec3 compute_uv(RenderTaskCommonData task, vec2 texture_size) {
-    RectWithSize task_rect = task.task_rect;
-    vec3 uv = vec3(0.0, 0.0, task.texture_layer_index);
-
-    vec2 uv0 = task_rect.p0 / texture_size;
-    vec2 uv1 = floor(task_rect.p0 + task_rect.size) / texture_size;
-    uv.xy = mix(uv0, uv1, aPosition.xy);
-
-    return uv;
-}
-
-void main(void) {
-    FilterTask filter_task = fetch_filter_task(aFilterRenderTaskAddress);
-    RectWithSize target_rect = filter_task.common_data.task_rect;
-
-    vec2 pos = target_rect.p0 + target_rect.size * aPosition.xy;
-
-    RenderTaskCommonData input_1_task;
-    if (aFilterInputCount > 0) {
-        vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
-        input_1_task = fetch_render_task_common_data(aFilterInput1TaskAddress);
-        vInput1UvRect = compute_uv_rect(input_1_task, texture_size);
-        vInput1Uv = compute_uv(input_1_task, texture_size);
-    }
-
-    RenderTaskCommonData input_2_task;
-    if (aFilterInputCount > 1) {
-        vec2 texture_size = vec2(textureSize(sColor1, 0).xy);
-        input_2_task = fetch_render_task_common_data(aFilterInput2TaskAddress);
-        vInput2UvRect = compute_uv_rect(input_2_task, texture_size);
-        vInput2Uv = compute_uv(input_2_task, texture_size);
-    }
-
-    vFilterInputCount = aFilterInputCount;
-    vFilterKind = aFilterKind;
-
-    // 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] = (aFilterGenericInt >> 12) & 0xf; // R
-    vFuncs[1] = (aFilterGenericInt >> 8)  & 0xf; // G
-    vFuncs[2] = (aFilterGenericInt >> 4)  & 0xf; // B
-    vFuncs[3] = (aFilterGenericInt)       & 0xf; // A
-
-    switch (aFilterKind) {
-        case FILTER_BLEND:
-            vData = ivec4(aFilterGenericInt, 0, 0, 0);
-            break;
-        case FILTER_FLOOD:
-            vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress);
-            break;
-        case FILTER_OPACITY:
-            vFloat0 = filter_task.user_data.x;
-            break;
-        case FILTER_COLOR_MATRIX:
-            vec4 mat_data[3] = fetch_from_gpu_cache_3_direct(aFilterExtraDataAddress);
-            vColorMat = mat3(mat_data[0].xyz, mat_data[1].xyz, mat_data[2].xyz);
-            vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress + ivec2(4, 0));
-            break;
-        case FILTER_DROP_SHADOW:
-            vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress);
-            break;
-        case FILTER_OFFSET:
-            vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
-            vFilterData0 = vec4(-filter_task.user_data.xy / texture_size, vec2(0.0));
-
-            RectWithSize task_rect = input_1_task.task_rect;
-            vec4 clipRect = vec4(task_rect.p0, task_rect.p0 + task_rect.size);
-            clipRect /= texture_size.xyxy;
-            vFilterData1 = clipRect;
-            break;
-        case FILTER_COMPONENT_TRANSFER:
-            vData = ivec4(aFilterExtraDataAddress, 0, 0);
-            break;
-        default:
-            break;
-    }
-
-    gl_Position = uTransform * vec4(pos, 0.0, 1.0);
-}
-#endif
-
-#ifdef WR_FRAGMENT_SHADER
-
-#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
-
-vec3 Multiply(vec3 Cb, vec3 Cs) {
-    return Cb * Cs;
-}
-
-vec3 Screen(vec3 Cb, vec3 Cs) {
-    return Cb + Cs - (Cb * Cs);
-}
-
-vec3 HardLight(vec3 Cb, vec3 Cs) {
-    vec3 m = Multiply(Cb, 2.0 * Cs);
-    vec3 s = Screen(Cb, 2.0 * Cs - 1.0);
-    vec3 edge = vec3(0.5, 0.5, 0.5);
-    return mix(m, s, step(edge, Cs));
-}
-
-// TODO: Worth doing with mix/step? Check GLSL output.
-float ColorDodge(float Cb, float Cs) {
-    if (Cb == 0.0)
-        return 0.0;
-    else if (Cs == 1.0)
-        return 1.0;
-    else
-        return min(1.0, Cb / (1.0 - Cs));
-}
-
-// TODO: Worth doing with mix/step? Check GLSL output.
-float ColorBurn(float Cb, float Cs) {
-    if (Cb == 1.0)
-        return 1.0;
-    else if (Cs == 0.0)
-        return 0.0;
-    else
-        return 1.0 - min(1.0, (1.0 - Cb) / Cs);
-}
-
-float SoftLight(float Cb, float Cs) {
-    if (Cs <= 0.5) {
-        return Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb);
-    } else {
-        float D;
-
-        if (Cb <= 0.25)
-            D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb;
-        else
-            D = sqrt(Cb);
-
-        return Cb + (2.0 * Cs - 1.0) * (D - Cb);
-    }
-}
-
-vec3 Difference(vec3 Cb, vec3 Cs) {
-    return abs(Cb - Cs);
-}
-
-vec3 Exclusion(vec3 Cb, vec3 Cs) {
-    return Cb + Cs - 2.0 * Cb * Cs;
-}
-
-// These functions below are taken from the spec.
-// There's probably a much quicker way to implement
-// them in GLSL...
-float Sat(vec3 c) {
-    return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b));
-}
-
-float Lum(vec3 c) {
-    vec3 f = vec3(0.3, 0.59, 0.11);
-    return dot(c, f);
-}
-
-vec3 ClipColor(vec3 C) {
-    float L = Lum(C);
-    float n = min(C.r, min(C.g, C.b));
-    float x = max(C.r, max(C.g, C.b));
-
-    if (n < 0.0)
-        C = L + (((C - L) * L) / (L - n));
-
-    if (x > 1.0)
-        C = L + (((C - L) * (1.0 - L)) / (x - L));
-
-    return C;
-}
-
-vec3 SetLum(vec3 C, float l) {
-    float d = l - Lum(C);
-    return ClipColor(C + d);
-}
-
-void SetSatInner(inout float Cmin, inout float Cmid, inout float Cmax, float s) {
-    if (Cmax > Cmin) {
-        Cmid = (((Cmid - Cmin) * s) / (Cmax - Cmin));
-        Cmax = s;
-    } else {
-        Cmid = 0.0;
-        Cmax = 0.0;
-    }
-    Cmin = 0.0;
-}
-
-vec3 SetSat(vec3 C, float s) {
-    if (C.r <= C.g) {
-        if (C.g <= C.b) {
-            SetSatInner(C.r, C.g, C.b, s);
-        } else {
-            if (C.r <= C.b) {
-                SetSatInner(C.r, C.b, C.g, s);
-            } else {
-                SetSatInner(C.b, C.r, C.g, s);
-            }
-        }
-    } else {
-        if (C.r <= C.b) {
-            SetSatInner(C.g, C.r, C.b, s);
-        } else {
-            if (C.g <= C.b) {
-                SetSatInner(C.g, C.b, C.r, s);
-            } else {
-                SetSatInner(C.b, C.g, C.r, s);
-            }
-        }
-    }
-    return C;
-}
-
-vec3 Hue(vec3 Cb, vec3 Cs) {
-    return SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb));
-}
-
-vec3 Saturation(vec3 Cb, vec3 Cs) {
-    return SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb));
-}
-
-vec3 Color(vec3 Cb, vec3 Cs) {
-    return SetLum(Cs, Lum(Cb));
-}
-
-vec3 Luminosity(vec3 Cb, vec3 Cs) {
-    return SetLum(Cb, Lum(Cs));
-}
-
-const int BlendMode_Normal      = 0;
-const int BlendMode_Multiply    = 1;
-const int BlendMode_Screen      = 2;
-const int BlendMode_Overlay     = 3;
-const int BlendMode_Darken      = 4;
-const int BlendMode_Lighten     = 5;
-const int BlendMode_ColorDodge  = 6;
-const int BlendMode_ColorBurn   = 7;
-const int BlendMode_HardLight   = 8;
-const int BlendMode_SoftLight   = 9;
-const int BlendMode_Difference  = 10;
-const int BlendMode_Exclusion   = 11;
-const int BlendMode_Hue         = 12;
-const int BlendMode_Saturation  = 13;
-const int BlendMode_Color       = 14;
-const int BlendMode_Luminosity  = 15;
-
-vec4 blend(vec4 Cs, vec4 Cb, int mode) {
-    vec4 result = vec4(1.0, 0.0, 0.0, 1.0);
-
-    switch (mode) {
-        case BlendMode_Normal:
-            result.rgb = Cs.rgb;
-            break;
-        case BlendMode_Multiply:
-            result.rgb = Multiply(Cb.rgb, Cs.rgb);
-            break;
-        case BlendMode_Screen:
-            result.rgb = Screen(Cb.rgb, Cs.rgb);
-            break;
-        case BlendMode_Overlay:
-            // Overlay is inverse of Hardlight
-            result.rgb = HardLight(Cs.rgb, Cb.rgb);
-            break;
-        case BlendMode_Darken:
-            result.rgb = min(Cs.rgb, Cb.rgb);
-            break;
-        case BlendMode_Lighten:
-            result.rgb = max(Cs.rgb, Cb.rgb);
-            break;
-        case BlendMode_ColorDodge:
-            result.r = ColorDodge(Cb.r, Cs.r);
-            result.g = ColorDodge(Cb.g, Cs.g);
-            result.b = ColorDodge(Cb.b, Cs.b);
-            break;
-        case BlendMode_ColorBurn:
-            result.r = ColorBurn(Cb.r, Cs.r);
-            result.g = ColorBurn(Cb.g, Cs.g);
-            result.b = ColorBurn(Cb.b, Cs.b);
-            break;
-        case BlendMode_HardLight:
-            result.rgb = HardLight(Cb.rgb, Cs.rgb);
-            break;
-        case BlendMode_SoftLight:
-            result.r = SoftLight(Cb.r, Cs.r);
-            result.g = SoftLight(Cb.g, Cs.g);
-            result.b = SoftLight(Cb.b, Cs.b);
-            break;
-        case BlendMode_Difference:
-            result.rgb = Difference(Cb.rgb, Cs.rgb);
-            break;
-        case BlendMode_Exclusion:
-            result.rgb = Exclusion(Cb.rgb, Cs.rgb);
-            break;
-        case BlendMode_Hue:
-            result.rgb = Hue(Cb.rgb, Cs.rgb);
-            break;
-        case BlendMode_Saturation:
-            result.rgb = Saturation(Cb.rgb, Cs.rgb);
-            break;
-        case BlendMode_Color:
-            result.rgb = Color(Cb.rgb, Cs.rgb);
-            break;
-        case BlendMode_Luminosity:
-            result.rgb = Luminosity(Cb.rgb, Cs.rgb);
-            break;
-        default: break;
-    }
-    vec3 rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
-    result = mix(vec4(Cb.rgb * Cb.a, Cb.a), vec4(rgb, 1.0), Cs.a);
-    return result;
-}
-
-// Based on the Gecko's implementation in
-// https://hg.mozilla.org/mozilla-central/file/91b4c3687d75/gfx/src/FilterSupport.cpp#l24
-// These could be made faster by sampling a lookup table stored in a float texture
-// with linear interpolation.
-
-vec3 SrgbToLinear(vec3 color) {
-    vec3 c1 = color / 12.92;
-    vec3 c2 = pow(color / 1.055 + vec3(0.055 / 1.055), vec3(2.4));
-    return if_then_else(lessThanEqual(color, vec3(0.04045)), c1, c2);
-}
-
-vec3 LinearToSrgb(vec3 color) {
-    vec3 c1 = color * 12.92;
-    vec3 c2 = vec3(1.055) * pow(color, vec3(1.0 / 2.4)) - vec3(0.055);
-    return if_then_else(lessThanEqual(color, vec3(0.0031308)), c1, c2);
-}
-
-// This function has to be factored out due to the following issue:
-// https://github.com/servo/webrender/wiki/Driver-issues#bug-1532245---switch-statement-inside-control-flow-inside-switch-statement-fails-to-compile-on-some-android-phones
-// (and now the words "default: default:" so angle_shader_validation.rs passes)
-vec4 ComponentTransfer(vec4 colora) {
-    // 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.
-    int offset = 0;
-    vec4 texel;
-    int k;
-
-    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_direct(vData.xy + ivec2(offset + k/4, 0));
-                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_direct(vData.xy + ivec2(offset, 0));
-                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_direct(vData.xy + ivec2(offset, 0));
-                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;
-}
-
-vec4 sampleInUvRect(sampler2DArray sampler, vec3 uv, vec4 uvRect) {
-    vec2 clamped = clamp(uv.xy, uvRect.xy, uvRect.zw);
-    return texture(sampler, vec3(clamped, uv.z), 0.0);
-}
-
-void main(void) {
-    vec4 Ca = vec4(0.0, 0.0, 0.0, 0.0);
-    vec4 Cb = vec4(0.0, 0.0, 0.0, 0.0);
-    if (vFilterInputCount > 0) {
-        Ca = sampleInUvRect(sColor0, vInput1Uv, vInput1UvRect);
-        if (Ca.a != 0.0) {
-            Ca.rgb /= Ca.a;
-        }
-    }
-    if (vFilterInputCount > 1) {
-        Cb = sampleInUvRect(sColor1, vInput2Uv, vInput2UvRect);
-        if (Cb.a != 0.0) {
-            Cb.rgb /= Cb.a;
-        }
-    }
-
-    vec4 result = vec4(1.0, 0.0, 0.0, 1.0);
-
-    bool needsPremul = true;
-
-    switch (vFilterKind) {
-        case FILTER_BLEND:
-            result = blend(Ca, Cb, vData.x);
-            needsPremul = false;
-            break;
-        case FILTER_FLOOD:
-            result = vFilterData0;
-            needsPremul = false;
-            break;
-        case FILTER_LINEAR_TO_SRGB:
-            result.rgb = LinearToSrgb(Ca.rgb);
-            result.a = Ca.a;
-            break;
-        case FILTER_SRGB_TO_LINEAR:
-            result.rgb = SrgbToLinear(Ca.rgb);
-            result.a = Ca.a;
-            break;
-        case FILTER_OPACITY:
-            result.rgb = Ca.rgb;
-            result.a = Ca.a * vFloat0;
-            break;
-        case FILTER_COLOR_MATRIX:
-            result.rgb = vColorMat * Ca.rgb + vFilterData0.rgb;
-            result.a = Ca.a;
-            break;
-        case FILTER_DROP_SHADOW:
-            vec4 shadow = vec4(vFilterData0.rgb, Cb.a * vFilterData0.a);
-            // Normal blend + source-over coposite
-            result = blend(Ca, shadow, BlendMode_Normal);
-            needsPremul = false;
-            break;
-        case FILTER_OFFSET:
-            vec2 offsetUv = vInput1Uv.xy + vFilterData0.xy;
-            result = sampleInUvRect(sColor0, vec3(offsetUv, vInput1Uv.z), vInput1UvRect);
-            result *= point_inside_rect(offsetUv, vFilterData1.xy, vFilterData1.zw);
-            needsPremul = false;
-            break;
-        case FILTER_COMPONENT_TRANSFER:
-            vec4 colora = Ca.a != 0.0 ? Ca / Ca.a : Ca;
-            result = ComponentTransfer(Ca);
-            break;
-        case FILTER_IDENTITY:
-            result = Ca;
-            break;
-        default:
-            break;
-    }
-
-    if (needsPremul) {
-        result.rgb *= result.a;
-    }
-
-    oFragColor = result;
-}
-#endif
--- a/gfx/wr/webrender/src/batch.rs
+++ b/gfx/wr/webrender/src/batch.rs
@@ -95,37 +95,16 @@ impl BatchTextures {
         }
     }
 
     pub fn color(texture: TextureSource) -> Self {
         BatchTextures {
             colors: [texture, texture, TextureSource::Invalid],
         }
     }
-
-    pub fn is_compatible_with(&self, other: &BatchTextures) -> bool {
-        self.colors.iter().zip(other.colors.iter()).all(|(t1, t2)| textures_compatible(*t1, *t2))
-    }
-
-    pub fn combine_textures(&self, other: BatchTextures) -> Option<BatchTextures> {
-        if !self.is_compatible_with(&other) {
-            return None;
-        }
-
-        let mut new_textures = BatchTextures::no_texture();
-        for (i, (color, other_color)) in self.colors.iter().zip(other.colors.iter()).enumerate() {
-            // If these textures are compatible, for each source either both sources are invalid or only one is not invalid.
-            new_textures.colors[i] = if *color == TextureSource::Invalid {
-                *other_color
-            } else {
-                *color
-            };
-        }
-        Some(new_textures)
-    }
 }
 
 #[derive(Copy, Clone, Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BatchKey {
     pub kind: BatchKind,
     pub blend_mode: BlendMode,
@@ -137,17 +116,20 @@ impl BatchKey {
         BatchKey {
             kind,
             blend_mode,
             textures,
         }
     }
 
     pub fn is_compatible_with(&self, other: &BatchKey) -> bool {
-        self.kind == other.kind && self.blend_mode == other.blend_mode && self.textures.is_compatible_with(&other.textures)
+        self.kind == other.kind && self.blend_mode == other.blend_mode &&
+            textures_compatible(self.textures.colors[0], other.textures.colors[0]) &&
+            textures_compatible(self.textures.colors[1], other.textures.colors[1]) &&
+            textures_compatible(self.textures.colors[2], other.textures.colors[2])
     }
 }
 
 #[inline]
 fn textures_compatible(t1: TextureSource, t2: TextureSource) -> bool {
     t1 == TextureSource::Invalid || t2 == TextureSource::Invalid || t1 == t2
 }
 
@@ -1653,50 +1635,16 @@ impl BatchBuilder {
                                     transform_kind,
                                     render_tasks,
                                     z_id,
                                     prim_info.clip_task_index,
                                     prim_vis_mask,
                                     ctx,
                                 );
                             }
-                            PictureCompositeMode::SvgFilter(..) => {
-                                let kind = BatchKind::Brush(
-                                    BrushBatchKind::Image(ImageBufferKind::Texture2DArray)
-                                );
-                                let (uv_rect_address, textures) = render_tasks.resolve_surface(
-                                    surface_task.expect("bug: surface must be allocated by now"),
-                                    gpu_cache,
-                                );
-                                let key = BatchKey::new(
-                                    kind,
-                                    non_segmented_blend_mode,
-                                    textures,
-                                );
-                                let prim_header_index = prim_headers.push(&prim_header, z_id, [
-                                    ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16),
-                                    RasterizationSpace::Screen as i32,
-                                    get_shader_opacity(1.0),
-                                    0,
-                                ]);
-
-                                self.add_brush_instance_to_batches(
-                                    key,
-                                    batch_features,
-                                    bounding_rect,
-                                    z_id,
-                                    INVALID_SEGMENT_INDEX,
-                                    EdgeAaSegmentMask::empty(),
-                                    clip_task_address,
-                                    brush_flags,
-                                    prim_header_index,
-                                    uv_rect_address.as_int(),
-                                    prim_vis_mask,
-                                );
-                            }
                         }
                     }
                     None => {
                         // If this picture is being drawn into an existing target (i.e. with
                         // no composition operation), recurse and add to the current batch list.
                         self.add_pic_to_batch(
                             picture,
                             ctx,
--- a/gfx/wr/webrender/src/display_list_flattener.rs
+++ b/gfx/wr/webrender/src/display_list_flattener.rs
@@ -1,16 +1,16 @@
 /* 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/. */
 
 use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter};
 use api::{ClipId, ColorF, CommonItemProperties, ComplexClipRegion, RasterSpace};
 use api::{DisplayItem, DisplayItemRef, ExtendMode, ExternalScrollId};
-use api::{FilterOp, FilterPrimitive, FontInstanceKey, GlyphInstance, GlyphOptions, GradientStop};
+use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, GradientStop};
 use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, ColorDepth};
 use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
 use api::{PropertyBinding, ReferenceFrame, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
 use api::{Shadow, SpaceAndClipInfo, SpatialId, StackingContext, StickyFrameDisplayItem};
 use api::{ClipMode, PrimitiveKeyKind, TransformStyle, YuvColorSpace, YuvData, TempFilterData};
 use api::units::*;
 use crate::clip::{ClipChainId, ClipRegion, ClipItemKey, ClipStore};
 use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, SpatialNodeIndex};
@@ -791,31 +791,29 @@ impl<'a> DisplayListFlattener<'a> {
         &mut self,
         traversal: &mut BuiltDisplayListIter<'a>,
         pipeline_id: PipelineId,
         stacking_context: &StackingContext,
         spatial_node_index: SpatialNodeIndex,
         origin: LayoutPoint,
         filters: ItemRange<FilterOp>,
         filter_datas: &[TempFilterData],
-        filter_primitives: ItemRange<FilterPrimitive>,
         is_backface_visible: bool,
         apply_pipeline_clip: bool,
     ) {
         // Avoid doing unnecessary work for empty stacking contexts.
         if traversal.current_stacking_context_empty() {
             traversal.skip_current_stacking_context();
             return;
         }
 
         let composition_operations = {
             CompositeOps::new(
                 stacking_context.filter_ops_for_compositing(filters),
                 stacking_context.filter_datas_for_compositing(filter_datas),
-                stacking_context.filter_primitives_for_compositing(filter_primitives),
                 stacking_context.mix_blend_mode_for_compositing(),
             )
         };
 
         let clip_chain_id = match stacking_context.clip_id {
             Some(clip_id) => self.id_to_index_mapper.get_clip_chain_id(clip_id),
             None => ClipChainId::NONE,
         };
@@ -1177,17 +1175,16 @@ impl<'a> DisplayListFlattener<'a> {
                 self.flatten_stacking_context(
                     &mut subtraversal,
                     pipeline_id,
                     &info.stacking_context,
                     space,
                     info.origin,
                     item.filters(),
                     item.filter_datas(),
-                    item.filter_primitives(),
                     info.is_backface_visible,
                     apply_pipeline_clip,
                 );
                 return Some(subtraversal);
             }
             DisplayItem::PushReferenceFrame(ref info) => {
                 let parent_space = self.get_space(&info.parent_spatial_id);
                 let mut subtraversal = item.sub_iter();
@@ -1307,20 +1304,19 @@ impl<'a> DisplayListFlattener<'a> {
                 let parent_space = self.get_space(&info.parent_spatial_id);
                 self.flatten_sticky_frame(
                     info,
                     parent_space,
                 );
             }
 
             // Do nothing; these are dummy items for the display list parser
-            DisplayItem::SetGradientStops |
-            DisplayItem::SetFilterOps |
-            DisplayItem::SetFilterData |
-            DisplayItem::SetFilterPrimitives => {}
+            DisplayItem::SetGradientStops => {}
+            DisplayItem::SetFilterOps => {}
+            DisplayItem::SetFilterData => {}
 
             DisplayItem::PopReferenceFrame |
             DisplayItem::PopStackingContext => {
                 unreachable!("Should have returned in parent method.")
             }
             DisplayItem::PushShadow(info) => {
                 let clip_and_scroll = self.get_clip_and_scroll(
                     &info.space_and_clip.clip_id,
@@ -1976,81 +1972,16 @@ impl<'a> DisplayListFlattener<'a> {
                 println!("\tis a composite picture for a stacking context with {:?}", filter);
             }
 
             // Run the optimize pass on this picture, to see if we can
             // collapse opacity and avoid drawing to an off-screen surface.
             self.prim_store.optimize_picture_if_possible(current_pic_index);
         }
 
-        if !stacking_context.composite_ops.filter_primitives.is_empty() {
-            let filter_datas = stacking_context.composite_ops.filter_datas.iter()
-                .map(|filter_data| filter_data.sanitize())
-                .map(|filter_data| {
-                    SFilterData {
-                        r_func: SFilterDataComponent::from_functype_values(
-                            filter_data.func_r_type, &filter_data.r_values),
-                        g_func: SFilterDataComponent::from_functype_values(
-                            filter_data.func_g_type, &filter_data.g_values),
-                        b_func: SFilterDataComponent::from_functype_values(
-                            filter_data.func_b_type, &filter_data.b_values),
-                        a_func: SFilterDataComponent::from_functype_values(
-                            filter_data.func_a_type, &filter_data.a_values),
-                    }
-                })
-                .collect();
-
-            // Sanitize filter inputs
-            for primitive in &mut stacking_context.composite_ops.filter_primitives {
-                primitive.sanitize();
-            }
-
-            let composite_mode = PictureCompositeMode::SvgFilter(
-                stacking_context.composite_ops.filter_primitives,
-                filter_datas,
-            );
-
-            let filter_pic_index = PictureIndex(self.prim_store.pictures
-                .alloc()
-                .init(PicturePrimitive::new_image(
-                    Some(composite_mode.clone()),
-                    Picture3DContext::Out,
-                    None,
-                    true,
-                    stacking_context.is_backface_visible,
-                    stacking_context.requested_raster_space,
-                    PrimitiveList::new(
-                        vec![cur_instance.clone()],
-                        &self.interners,
-                    ),
-                    stacking_context.spatial_node_index,
-                    None,
-                    PictureOptions::default(),
-                ))
-            );
-
-            current_pic_index = filter_pic_index;
-            cur_instance = create_prim_instance(
-                current_pic_index,
-                Some(composite_mode).into(),
-                stacking_context.is_backface_visible,
-                ClipChainId::NONE,
-                stacking_context.spatial_node_index,
-                &mut self.interners,
-            );
-
-            if cur_instance.is_chased() {
-                println!("\tis a composite picture for a stacking context with an SVG filter");
-            }
-
-            // Run the optimize pass on this picture, to see if we can
-            // collapse opacity and avoid drawing to an off-screen surface.
-            self.prim_store.optimize_picture_if_possible(current_pic_index);
-        }
-
         // Same for mix-blend-mode, except we can skip if this primitive is the first in the parent
         // stacking context.
         // From https://drafts.fxtf.org/compositing-1/#generalformula, the formula for blending is:
         // Cs = (1 - ab) x Cs + ab x Blend(Cb, Cs)
         // where
         // Cs = Source color
         // ab = Backdrop alpha
         // Cb = Backdrop color
@@ -3127,21 +3058,16 @@ impl FlattenedStackingContext {
             return false;
         }
 
         // If there are filters / mix-blend-mode
         if !self.composite_ops.filters.is_empty() {
             return false;
         }
 
-        // If there are svg filters
-        if !self.composite_ops.filter_primitives.is_empty() {
-            return false;
-        }
-
         // We can skip mix-blend modes if they are the first primitive in a stacking context,
         // see pop_stacking_context for a full explanation.
         if !self.composite_ops.mix_blend_mode.is_none() &&
             !parent.primitives.is_empty() {
             return false;
         }
 
         // If backface visibility is explicitly set.
--- a/gfx/wr/webrender/src/filterdata.rs
+++ b/gfx/wr/webrender/src/filterdata.rs
@@ -117,44 +117,34 @@ impl From<SFilterDataKey> for SFilterDat
     fn from(item: SFilterDataKey) -> Self {
         SFilterDataTemplate {
             data: item.data,
             gpu_cache_handle: GpuCacheHandle::new(),
         }
     }
 }
 
-impl SFilterData {
-    pub fn is_identity(&self) -> bool {
-        self.r_func == SFilterDataComponent::Identity
-            && self.g_func == SFilterDataComponent::Identity
-            && self.b_func == SFilterDataComponent::Identity
-            && self.a_func == SFilterDataComponent::Identity
-    }
-
-    pub fn update(&self, mut request: GpuDataRequest) {
-        push_component_transfer_data(&self.r_func, &mut request);
-        push_component_transfer_data(&self.g_func, &mut request);
-        push_component_transfer_data(&self.b_func, &mut request);
-        push_component_transfer_data(&self.a_func, &mut request);
-        assert!(!self.is_identity());
-    }
-}
-
 impl SFilterDataTemplate {
     /// Update the GPU cache for a given filter data template. This may be called multiple
     /// times per frame, by each primitive reference that refers to this interned
     /// template. The initial request call to the GPU cache ensures that work is only
     /// done if the cache entry is invalid (due to first use or eviction).
     pub fn update(
         &mut self,
         frame_state: &mut FrameBuildingState,
     ) {
-        if let Some(request) = frame_state.gpu_cache.request(&mut self.gpu_cache_handle) {
-            self.data.update(request);
+        if let Some(mut request) = frame_state.gpu_cache.request(&mut self.gpu_cache_handle) {
+            push_component_transfer_data(&self.data.r_func, &mut request);
+            push_component_transfer_data(&self.data.g_func, &mut request);
+            push_component_transfer_data(&self.data.b_func, &mut request);
+            push_component_transfer_data(&self.data.a_func, &mut request);
+            assert!(self.data.r_func != SFilterDataComponent::Identity
+                 || self.data.g_func != SFilterDataComponent::Identity
+                 || self.data.b_func != SFilterDataComponent::Identity
+                 || self.data.a_func != SFilterDataComponent::Identity);
         }
     }
 }
 
 impl intern::Internable for FilterDataIntern {
     type Key = SFilterDataKey;
     type StoreData = SFilterDataTemplate;
     type InternData = ();
--- a/gfx/wr/webrender/src/gpu_types.rs
+++ b/gfx/wr/webrender/src/gpu_types.rs
@@ -104,30 +104,16 @@ pub struct BlurInstance {
 #[repr(C)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct ScalingInstance {
     pub task_address: RenderTaskAddress,
     pub src_task_address: RenderTaskAddress,
 }
 
-#[derive(Debug)]
-#[repr(C)]
-#[cfg_attr(feature = "capture", derive(Serialize))]
-#[cfg_attr(feature = "replay", derive(Deserialize))]
-pub struct SvgFilterInstance {
-    pub task_address: RenderTaskAddress,
-    pub input_1_task_address: RenderTaskAddress,
-    pub input_2_task_address: RenderTaskAddress,
-    pub kind: u16,
-    pub input_count: u16,
-    pub generic_int: u16,
-    pub extra_data_address: GpuCacheAddress,
-}
-
 #[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
 #[repr(C)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum BorderSegment {
     TopLeft,
     TopRight,
     BottomRight,
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -1,25 +1,24 @@
 /* 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/. */
 
-use api::{MixBlendMode, PipelineId, PremultipliedColorF, FilterPrimitiveKind};
-use api::{PropertyBinding, PropertyBindingId, FilterPrimitive, FontRenderMode};
+use api::{MixBlendMode, PipelineId, PremultipliedColorF};
+use api::{PropertyBinding, PropertyBindingId, FontRenderMode};
 use api::{DebugFlags, RasterSpace, ImageKey, ColorF};
 use api::units::*;
 use crate::box_shadow::{BLUR_SAMPLE_SCALE};
 use crate::clip::{ClipStore, ClipDataStore, ClipChainInstance};
 use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX,
     ClipScrollTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace, CoordinateSystemId
 };
 use crate::debug_colors;
 use euclid::{vec3, TypedPoint2D, TypedScale, TypedSize2D, Vector2D, TypedRect};
 use euclid::approxeq::ApproxEq;
-use crate::filterdata::SFilterData;
 use crate::frame_builder::{FrameVisibilityContext, FrameVisibilityState};
 use crate::intern::ItemUid;
 use crate::internal_types::{FastHashMap, FastHashSet, PlaneSplitter, Filter};
 use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PictureContext};
 use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
 use crate::gpu_types::UvRectKind;
 use plane_split::{Clipper, Polygon, Splitter};
 use crate::prim_store::{SpaceMapper, PrimitiveVisibilityMask, PointKey, PrimitiveTemplateKind};
@@ -1569,76 +1568,16 @@ pub enum PictureCompositeMode {
     /// Apply a component transfer filter.
     ComponentTransferFilter(FilterDataHandle),
     /// Draw to intermediate surface, copy straight across. This
     /// is used for CSS isolation, and plane splitting.
     Blit(BlitReason),
     /// Used to cache a picture as a series of tiles.
     TileCache {
     },
-    /// Apply an SVG filter
-    SvgFilter(Vec<FilterPrimitive>, Vec<SFilterData>),
-}
-
-impl PictureCompositeMode {
-    pub fn inflate_picture_rect(&self, picture_rect: PictureRect, inflation_factor: f32) -> PictureRect {
-        let mut result_rect = picture_rect;
-        match self {
-            PictureCompositeMode::Filter(filter) => match filter {
-                Filter::Blur(_) => {
-                    result_rect = picture_rect.inflate(inflation_factor, inflation_factor);
-                },
-                Filter::DropShadows(shadows) => {
-                    let mut max_inflation: f32 = 0.0;
-                    for shadow in shadows {
-                        let inflation_factor = shadow.blur_radius.round() * BLUR_SAMPLE_SCALE;
-                        max_inflation = max_inflation.max(inflation_factor);
-                    }
-                    result_rect = picture_rect.inflate(max_inflation, max_inflation);
-                },
-                _ => {}
-            }
-            PictureCompositeMode::SvgFilter(primitives, _) => {
-                let mut output_rects = Vec::with_capacity(primitives.len());
-                for (cur_index, primitive) in primitives.iter().enumerate() {
-                    let output_rect = match primitive.kind {
-                        FilterPrimitiveKind::Blur(ref primitive) => {
-                            let input = primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect);
-                            let inflation_factor = primitive.radius.round() * BLUR_SAMPLE_SCALE;
-                            input.inflate(inflation_factor, inflation_factor)
-                        }
-                        FilterPrimitiveKind::DropShadow(ref primitive) => {
-                            let inflation_factor = primitive.shadow.blur_radius.round() * BLUR_SAMPLE_SCALE;
-                            let input = primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect);
-                            let shadow_rect = input.inflate(inflation_factor, inflation_factor);
-                            input.union(&shadow_rect.translate(&(primitive.shadow.offset * TypedScale::new(1.0))))
-                        }
-                        FilterPrimitiveKind::Blend(ref primitive) => {
-                            primitive.input1.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect)
-                                .union(&primitive.input2.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect))
-                        }
-                        FilterPrimitiveKind::Identity(ref primitive) =>
-                            primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
-                        FilterPrimitiveKind::Opacity(ref primitive) =>
-                            primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
-                        FilterPrimitiveKind::ColorMatrix(ref primitive) =>
-                            primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
-                        FilterPrimitiveKind::ComponentTransfer(ref primitive) =>
-                            primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
-
-                        FilterPrimitiveKind::Flood(..) => picture_rect,
-                    };
-                    output_rects.push(output_rect);
-                    result_rect = result_rect.union(&output_rect);
-                }
-            }
-            _ => {},
-        }
-        result_rect
-    }
 }
 
 /// Enum value describing the place of a picture in a 3D context.
 #[derive(Clone, Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 pub enum Picture3DContext<C> {
     /// The picture is not a part of 3D context sub-hierarchy.
     Out,
@@ -1994,18 +1933,17 @@ impl PicturePrimitive {
     pub fn can_use_segments(&self) -> bool {
         match self.raster_config {
             // TODO(gw): Support brush segment rendering for filter and mix-blend
             //           shaders. It's possible this already works, but I'm just
             //           applying this optimization to Blit mode for now.
             Some(RasterConfig { composite_mode: PictureCompositeMode::MixBlend(..), .. }) |
             Some(RasterConfig { composite_mode: PictureCompositeMode::Filter(..), .. }) |
             Some(RasterConfig { composite_mode: PictureCompositeMode::ComponentTransferFilter(..), .. }) |
-            Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) |
-            Some(RasterConfig { composite_mode: PictureCompositeMode::SvgFilter(..), .. }) |
+            Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, ..}) |
             None => {
                 false
             }
             Some(RasterConfig { composite_mode: PictureCompositeMode::Blit(reason), ..}) => {
                 reason == BlitReason::CLIP
             }
         }
     }
@@ -2499,50 +2437,16 @@ impl PicturePrimitive {
                             device_pixel_scale,
                             PrimitiveVisibilityMask::all(),
                         );
 
                         let render_task_id = frame_state.render_tasks.add(picture_task);
 
                         Some((render_task_id, render_task_id))
                     }
-                    PictureCompositeMode::SvgFilter(ref primitives, ref filter_datas) => {
-                        let uv_rect_kind = calculate_uv_rect_kind(
-                            &pic_rect,
-                            &transform,
-                            &clipped,
-                            device_pixel_scale,
-                            true,
-                        );
-
-                        let picture_task = RenderTask::new_picture(
-                            RenderTaskLocation::Dynamic(None, clipped.size),
-                            unclipped.size,
-                            pic_index,
-                            clipped.origin,
-                            uv_rect_kind,
-                            surface_spatial_node_index,
-                            device_pixel_scale,
-                            PrimitiveVisibilityMask::all(),
-                        );
-
-                        let picture_task_id = frame_state.render_tasks.add(picture_task);
-
-                        let filter_task_id = RenderTask::new_svg_filter(
-                            primitives,
-                            filter_datas,
-                            &mut frame_state.render_tasks,
-                            clipped.size,
-                            uv_rect_kind,
-                            picture_task_id,
-                            device_pixel_scale,
-                        );
-
-                        Some((filter_task_id, picture_task_id))
-                    }
                 };
 
                 if let Some((root, port)) = dep_info {
                     frame_state.surfaces[raster_config.surface_index.0].render_tasks = Some(SurfaceRenderTasks {
                         root,
                         port,
                     });
 
@@ -2586,18 +2490,17 @@ impl PicturePrimitive {
             Some(RasterConfig { ref composite_mode, .. }) => {
                 let subpixel_mode = match composite_mode {
                     PictureCompositeMode::TileCache { .. } => {
                         self.tile_cache.as_ref().unwrap().subpixel_mode
                     }
                     PictureCompositeMode::Blit(..) |
                     PictureCompositeMode::ComponentTransferFilter(..) |
                     PictureCompositeMode::Filter(..) |
-                    PictureCompositeMode::MixBlend(..) |
-                    PictureCompositeMode::SvgFilter(..) => {
+                    PictureCompositeMode::MixBlend(..) => {
                         // TODO(gw): We can take advantage of the same logic that
                         //           exists in the opaque rect detection for tile
                         //           caches, to allow subpixel text on other surfaces
                         //           that can be detected as opaque.
                         SubpixelMode::Deny
                     }
                 };
 
@@ -2833,40 +2736,24 @@ impl PicturePrimitive {
                     if self.options.inflate_if_required {
                         // The amount of extra space needed for primitives inside
                         // this picture to ensure the visibility check is correct.
                         BLUR_SAMPLE_SCALE * blur_radius
                     } else {
                         0.0
                     }
                 }
-                PictureCompositeMode::SvgFilter(ref primitives, _) if self.options.inflate_if_required => {
-                    let mut max = 0.0;
-                    for primitive in primitives {
-                        if let FilterPrimitiveKind::Blur(ref blur) = primitive.kind {
-                            max = f32::max(max, blur.radius * BLUR_SAMPLE_SCALE);
-                        }
-                    }
-                    max
-                }
                 _ => {
                     0.0
                 }
             };
 
-            // Filters must be applied before transforms, to do this, we can mark this picture as establishing a raster root.
-            let has_svg_filter = if let PictureCompositeMode::SvgFilter(..) = composite_mode {
-                true
-            } else {
-                false
-            };
-
-            // Check if there is perspective or if an SVG filter is applied, and thus whether a new
+            // Check if there is perspective, and thus whether a new
             // rasterization root should be established.
-            let establishes_raster_root = has_svg_filter || frame_context.clip_scroll_tree
+            let establishes_raster_root = frame_context.clip_scroll_tree
                 .get_relative_transform(surface_spatial_node_index, parent_raster_node_index)
                 .is_perspective();
 
             let surface = SurfaceInfo::new(
                 surface_spatial_node_index,
                 if establishes_raster_root {
                     surface_spatial_node_index
                 } else {
@@ -2943,22 +2830,36 @@ impl PicturePrimitive {
                 surface.rect = surface.rect.union(&cluster_rect);
             }
         }
 
         // If this picture establishes a surface, then map the surface bounding
         // rect into the parent surface coordinate space, and propagate that up
         // to the parent.
         if let Some(ref mut raster_config) = self.raster_config {
-            let surface = state.current_surface_mut();
-            // Inflate the local bounding rect if required by the filter effect.
-            // This inflaction factor is to be applied to the surface itself.
-            surface.rect = raster_config.composite_mode.inflate_picture_rect(surface.rect, surface.inflation_factor);
-
-            let mut surface_rect = surface.rect * TypedScale::new(1.0);
+            let mut surface_rect = {
+                let surface = state.current_surface_mut();
+                // Inflate the local bounding rect if required by the filter effect.
+                // This inflaction factor is to be applied to the surface itsefl.
+                // TODO: in prepare_for_render we round before multiplying with the
+                // blur sample scale. Should we do this here as well?
+                let inflation_size = match raster_config.composite_mode {
+                    PictureCompositeMode::Filter(Filter::Blur(_)) => surface.inflation_factor,
+                    PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
+                        let mut max = 0.0;
+                        for shadow in shadows {
+                            max = f32::max(max, shadow.blur_radius * BLUR_SAMPLE_SCALE);
+                        }
+                        max.ceil()
+                    }
+                    _ => 0.0,
+                };
+                surface.rect = surface.rect.inflate(inflation_size, inflation_size);
+                surface.rect * TypedScale::new(1.0)
+            };
 
             // Pop this surface from the stack
             let surface_index = state.pop_surface();
             debug_assert_eq!(surface_index, raster_config.surface_index);
 
             // Snapping may change the local rect slightly, and as such should just be
             // considered an estimated size for determining if we need raster roots and
             // preparing the tile cache.
@@ -3084,18 +2985,17 @@ impl PicturePrimitive {
                     _ => {}
                 }
             }
             PictureCompositeMode::ComponentTransferFilter(handle) => {
                 let filter_data = &mut data_stores.filter_data[handle];
                 filter_data.update(frame_state);
             }
             PictureCompositeMode::MixBlend(..) |
-            PictureCompositeMode::Blit(_) |
-            PictureCompositeMode::SvgFilter(..) => {}
+            PictureCompositeMode::Blit(_) => {}
         }
 
         true
     }
 }
 
 // Calculate a single homogeneous screen-space UV for a picture.
 fn calculate_screen_uv(
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -5,16 +5,17 @@
 use api::{BorderRadius, ClipMode, ColorF};
 use api::{ImageRendering, RepeatMode};
 use api::{PremultipliedColorF, PropertyBinding, Shadow, GradientStop};
 use api::{BoxShadowClipMode, LineStyle, LineOrientation, BorderStyle};
 use api::{PrimitiveKeyKind};
 use api::units::*;
 use crate::border::{get_max_scale_for_border, build_border_instances};
 use crate::border::BorderSegmentCacheKey;
+use crate::box_shadow::{BLUR_SAMPLE_SCALE};
 use crate::clip::{ClipStore};
 use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace};
 use crate::clip::{ClipDataStore, ClipNodeFlags, ClipChainId, ClipChainInstance, ClipItem};
 use crate::debug_colors;
 use crate::debug_render::DebugItem;
 use crate::display_list_flattener::{CreateShadow, IsVisible};
 use euclid::{SideOffsets2D, TypedTransform3D, TypedRect, TypedScale, TypedSize2D, TypedPoint2D};
 use euclid::approxeq::ApproxEq;
@@ -2247,17 +2248,28 @@ impl PrimitiveStore {
         // and stretch size. Drop shadow filters also depend on the local rect
         // size for the extra GPU cache data handle.
         // TODO(gw): In future, if we support specifying a flag which gets the
         //           stretch size from the segment rect in the shaders, we can
         //           remove this invalidation here completely.
         if let Some(ref raster_config) = pic.raster_config {
             // Inflate the local bounding rect if required by the filter effect.
             // This inflaction factor is to be applied to the surface itself.
-            surface_rect = raster_config.composite_mode.inflate_picture_rect(surface_rect, surface.inflation_factor);
+            let inflation_size = match raster_config.composite_mode {
+                PictureCompositeMode::Filter(Filter::Blur(_)) => surface.inflation_factor,
+                PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
+                    let mut max = 0.0;
+                    for shadow in shadows {
+                        max = f32::max(max, shadow.blur_radius * BLUR_SAMPLE_SCALE);
+                    }
+                    max.ceil()
+                }
+                _ => 0.0,
+            };
+            surface_rect = surface_rect.inflate(inflation_size, inflation_size);
 
             // Layout space for the picture is picture space from the
             // perspective of its child primitives.
             let pic_local_rect = surface_rect * TypedScale::new(1.0);
             if pic.snapped_local_rect != pic_local_rect {
                 match raster_config.composite_mode {
                     PictureCompositeMode::Filter(Filter::DropShadows(..)) => {
                         for handle in &pic.extra_gpu_data_handles {
--- a/gfx/wr/webrender/src/prim_store/picture.rs
+++ b/gfx/wr/webrender/src/prim_store/picture.rs
@@ -1,43 +1,28 @@
 /* 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/. */
 
 use api::{
-    ColorU, MixBlendMode, FilterPrimitiveInput, FilterPrimitiveKind, ColorSpace,
+    ColorU, MixBlendMode,
     PropertyBinding, PropertyBindingId,
 };
 use api::units::{Au, LayoutSize, LayoutVector2D};
+use crate::intern::ItemUid;
 use crate::display_list_flattener::IsVisible;
-use crate::filterdata::SFilterData;
-use crate::intern::ItemUid;
 use crate::intern::{Internable, InternDebug, Handle as InternHandle};
 use crate::internal_types::{LayoutPrimitiveInfo, Filter};
 use crate::picture::PictureCompositeMode;
 use crate::prim_store::{
     PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
     PrimitiveInstanceKind, PrimitiveSceneData, PrimitiveStore, VectorKey,
     InternablePrimitive,
 };
 
-#[cfg_attr(feature = "capture", derive(Serialize))]
-#[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
-pub enum FilterPrimitiveKey {
-    Identity(ColorSpace, FilterPrimitiveInput),
-    Flood(ColorSpace, ColorU),
-    Blend(ColorSpace, MixBlendMode, FilterPrimitiveInput, FilterPrimitiveInput),
-    Blur(ColorSpace, Au, FilterPrimitiveInput),
-    Opacity(ColorSpace, Au, FilterPrimitiveInput),
-    ColorMatrix(ColorSpace, [Au; 20], FilterPrimitiveInput),
-    DropShadow(ColorSpace, (VectorKey, Au, ColorU), FilterPrimitiveInput),
-    ComponentTransfer(ColorSpace, FilterPrimitiveInput, Vec<SFilterData>),
-}
-
 /// Represents a hashable description of how a picture primitive
 /// will be composited into its parent.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
 pub enum PictureCompositeKey {
     // No visual compositing effect
     Identity,
@@ -54,17 +39,16 @@ pub enum PictureCompositeKey {
     Saturate(Au),
     Sepia(Au),
     DropShadows(Vec<(VectorKey, Au, ColorU)>),
     ColorMatrix([Au; 20]),
     SrgbToLinear,
     LinearToSrgb,
     ComponentTransfer(ItemUid),
     Flood(ColorU),
-    SvgFilter(Vec<FilterPrimitiveKey>),
 
     // MixBlendMode
     Multiply,
     Screen,
     Overlay,
     Darken,
     Lighten,
     ColorDodge,
@@ -141,48 +125,16 @@ impl From<Option<PictureCompositeMode>> 
                     }
                     Filter::ComponentTransfer => unreachable!(),
                     Filter::Flood(color) => PictureCompositeKey::Flood(color.into()),
                 }
             }
             Some(PictureCompositeMode::ComponentTransferFilter(handle)) => {
                 PictureCompositeKey::ComponentTransfer(handle.uid())
             }
-            Some(PictureCompositeMode::SvgFilter(filter_primitives, filter_data)) => {
-                PictureCompositeKey::SvgFilter(filter_primitives.into_iter().map(|primitive| {
-                    match primitive.kind {
-                        FilterPrimitiveKind::Identity(identity) => FilterPrimitiveKey::Identity(primitive.color_space, identity.input),
-                        FilterPrimitiveKind::Blend(blend) => FilterPrimitiveKey::Blend(primitive.color_space, blend.mode, blend.input1, blend.input2),
-                        FilterPrimitiveKind::Flood(flood) => FilterPrimitiveKey::Flood(primitive.color_space, flood.color.into()),
-                        FilterPrimitiveKind::Blur(blur) => FilterPrimitiveKey::Blur(primitive.color_space, Au::from_f32_px(blur.radius), blur.input),
-                        FilterPrimitiveKind::Opacity(opacity) =>
-                            FilterPrimitiveKey::Opacity(primitive.color_space, Au::from_f32_px(opacity.opacity), opacity.input),
-                        FilterPrimitiveKind::ColorMatrix(color_matrix) => {
-                            let mut quantized_values: [Au; 20] = [Au(0); 20];
-                            for (value, result) in color_matrix.matrix.iter().zip(quantized_values.iter_mut()) {
-                                *result = Au::from_f32_px(*value);
-                            }
-                            FilterPrimitiveKey::ColorMatrix(primitive.color_space, quantized_values, color_matrix.input)
-                        }
-                        FilterPrimitiveKind::DropShadow(drop_shadow) => {
-                            FilterPrimitiveKey::DropShadow(
-                                primitive.color_space,
-                                (
-                                    drop_shadow.shadow.offset.into(),
-                                    Au::from_f32_px(drop_shadow.shadow.blur_radius),
-                                    drop_shadow.shadow.color.into(),
-                                ),
-                                drop_shadow.input,
-                            )
-                        }
-                        FilterPrimitiveKind::ComponentTransfer(component_transfer) =>
-                            FilterPrimitiveKey::ComponentTransfer(primitive.color_space, component_transfer.input, filter_data.clone()),
-                    }
-                }).collect())
-            }
             Some(PictureCompositeMode::Blit(_)) |
             Some(PictureCompositeMode::TileCache { .. }) |
             None => {
                 PictureCompositeKey::Identity
             }
         }
     }
 }
--- a/gfx/wr/webrender/src/render_task.rs
+++ b/gfx/wr/webrender/src/render_task.rs
@@ -1,25 +1,24 @@
 /* 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/. */
 
-use api::{ImageDescriptor, ImageFormat, FilterPrimitive, FilterPrimitiveInput, FilterPrimitiveKind};
-use api::{LineStyle, LineOrientation, ClipMode, DirtyRect, MixBlendMode, ColorF, ColorSpace};
+use api::{ImageDescriptor, ImageFormat};
+use api::{LineStyle, LineOrientation, ClipMode, DirtyRect};
 use api::units::*;
 #[cfg(feature = "pathfinder")]
 use api::FontRenderMode;
 use crate::border::BorderSegmentCacheKey;
 use crate::box_shadow::{BoxShadowCacheKey};
 use crate::clip::{ClipDataStore, ClipItem, ClipStore, ClipNodeRange, ClipNodeFlags};
 use crate::clip_scroll_tree::SpatialNodeIndex;
 use crate::device::TextureFilter;
 #[cfg(feature = "pathfinder")]
 use euclid::{TypedPoint2D, TypedVector2D};
-use crate::filterdata::SFilterData;
 use crate::frame_builder::FrameBuilderConfig;
 use crate::freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
 use crate::glyph_rasterizer::GpuGlyphCacheKey;
 use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
 use crate::gpu_types::{BorderInstance, ImageSource, UvRectKind, SnapOffsets};
 use crate::internal_types::{CacheTextureId, FastHashMap, LayerIndex, SavedTargetIndex, TextureSource};
 #[cfg(feature = "pathfinder")]
 use pathfinder_partitioner::mesh::Mesh;
@@ -350,25 +349,25 @@ impl RenderTaskGraph {
 
                     continue;
                 }
 
                 // Our dependency is an even number of passes behind, need
                 // to insert a blit to ensure we don't read and write from
                 // the same target.
 
-                let child_task_id = RenderTaskId {
+                let task_id = RenderTaskId {
                     index: child_task_index as u32,
                     #[cfg(debug_assertions)]
                     frame_id: self.frame_id,
                 };
 
                 let mut blit = RenderTask::new_blit(
-                    self.tasks[child_task_index].location.size(),
-                    BlitSource::RenderTask { task_id: child_task_id },
+                    self.tasks[task_index].location.size(),
+                    BlitSource::RenderTask { task_id },
                 );
 
                 // Mark for saving if the blit is more than pass appart from
                 // our task.
                 if child_pass_index < pass_index - 2 {
                     blit.mark_for_saving();
                 }
 
@@ -378,17 +377,17 @@ impl RenderTaskGraph {
                     frame_id: self.frame_id,
                 };
 
                 self.tasks.push(blit);
 
                 passes[child_pass_index as usize + 1].tasks.push(blit_id);
 
                 self.tasks[task_index].children[nth_child] = blit_id;
-                task_redirects[child_task_index] = Some(blit_id);
+                task_redirects[task_index] = Some(blit_id);
             }
         }
     }
 
     pub fn get_task_address(&self, id: RenderTaskId) -> RenderTaskAddress {
         #[cfg(all(debug_assertions, not(feature = "replay")))]
         debug_assert_eq!(self.frame_id, id.frame_id);
         RenderTaskAddress(id.index as u16)
@@ -614,43 +613,16 @@ pub struct LineDecorationTask {
     pub style: LineStyle,
     pub orientation: LineOrientation,
     pub local_size: LayoutSize,
 }
 
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-pub enum SvgFilterInfo {
-    Blend(MixBlendMode),
-    Flood(ColorF),
-    LinearToSrgb,
-    SrgbToLinear,
-    Opacity(f32),
-    ColorMatrix(Box<[f32; 20]>),
-    DropShadow(ColorF),
-    Offset(DeviceVector2D),
-    ComponentTransfer(SFilterData),
-    // TODO: This is used as a hack to ensure that a blur task's input is always in the blur's previous pass.
-    Identity,
-}
-
-#[derive(Debug)]
-#[cfg_attr(feature = "capture", derive(Serialize))]
-#[cfg_attr(feature = "replay", derive(Deserialize))]
-pub struct SvgFilterTask {
-    pub info: SvgFilterInfo,
-    pub extra_gpu_cache_handle: Option<GpuCacheHandle>,
-    pub uv_rect_handle: GpuCacheHandle,
-    uv_rect_kind: UvRectKind,
-}
-
-#[derive(Debug)]
-#[cfg_attr(feature = "capture", derive(Serialize))]
-#[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct RenderTaskData {
     pub data: [f32; FLOATS_PER_RENDER_TASK_INFO],
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum RenderTaskKind {
     Picture(PictureTask),
@@ -661,17 +633,16 @@ pub enum RenderTaskKind {
     #[allow(dead_code)]
     Glyph(GlyphTask),
     Readback(DeviceIntRect),
     Scaling(ScalingTask),
     Blit(BlitTask),
     Border(BorderTask),
     LineDecoration(LineDecorationTask),
     Gradient(GradientTask),
-    SvgFilter(SvgFilterTask),
     #[cfg(test)]
     Test(RenderTargetKind),
 }
 
 impl RenderTaskKind {
     pub fn as_str(&self) -> &'static str {
         match *self {
             RenderTaskKind::Picture(..) => "Picture",
@@ -681,17 +652,16 @@ impl RenderTaskKind {
             RenderTaskKind::HorizontalBlur(..) => "HorizontalBlur",
             RenderTaskKind::Glyph(..) => "Glyph",
             RenderTaskKind::Readback(..) => "Readback",
             RenderTaskKind::Scaling(..) => "Scaling",
             RenderTaskKind::Blit(..) => "Blit",
             RenderTaskKind::Border(..) => "Border",
             RenderTaskKind::LineDecoration(..) => "LineDecoration",
             RenderTaskKind::Gradient(..) => "Gradient",
-            RenderTaskKind::SvgFilter(..) => "SvgFilter",
             #[cfg(test)]
             RenderTaskKind::Test(..) => "Test",
         }
     }
 }
 
 #[derive(Debug, Copy, Clone, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
@@ -1197,295 +1167,16 @@ impl RenderTask {
             RenderTaskKind::Scaling(ScalingTask {
                 target_kind,
                 uv_rect_kind,
             }),
             ClearMode::DontCare,
         )
     }
 
-    pub fn new_svg_filter(
-        filter_primitives: &[FilterPrimitive],
-        filter_datas: &[SFilterData],
-        render_tasks: &mut RenderTaskGraph,
-        content_size: DeviceIntSize,
-        uv_rect_kind: UvRectKind,
-        original_task_id: RenderTaskId,
-        device_pixel_scale: DevicePixelScale,
-    ) -> RenderTaskId {
-
-        if filter_primitives.is_empty() {
-            return original_task_id;
-        }
-
-        // Resolves the input to a filter primitive
-        let get_task_input = |
-            input: &FilterPrimitiveInput,
-            filter_primitives: &[FilterPrimitive],
-            render_tasks: &mut RenderTaskGraph,
-            cur_index: usize,
-            outputs: &[RenderTaskId],
-            original: RenderTaskId,
-            color_space: ColorSpace,
-        | {
-            // TODO(cbrewster): Not sure we can assume that the original input is sRGB.
-            let (mut task_id, input_color_space) = match input.to_index(cur_index) {
-                Some(index) => (outputs[index], filter_primitives[index].color_space),
-                None => (original, ColorSpace::Srgb),
-            };
-
-            match (input_color_space, color_space) {
-                (ColorSpace::Srgb, ColorSpace::LinearRgb) => {
-                    let task = RenderTask::new_svg_filter_primitive(
-                        vec![task_id],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::SrgbToLinear,
-                    );
-                    task_id = render_tasks.add(task);
-                },
-                (ColorSpace::LinearRgb, ColorSpace::Srgb) => {
-                    let task = RenderTask::new_svg_filter_primitive(
-                        vec![task_id],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::LinearToSrgb,
-                    );
-                    task_id = render_tasks.add(task);
-                },
-                _ => {},
-            }
-
-            task_id
-        };
-
-        let mut outputs = vec![];
-        let mut cur_filter_data = 0;
-        for (cur_index, primitive) in filter_primitives.iter().enumerate() {
-            let render_task_id = match primitive.kind {
-                FilterPrimitiveKind::Identity(ref identity) => {
-                    // Identity does not create a task, it provides its input's render task
-                    get_task_input(
-                        &identity.input,
-                        filter_primitives,
-                        render_tasks,
-                        cur_index,
-                        &outputs,
-                        original_task_id,
-                        primitive.color_space
-                    )
-                }
-                FilterPrimitiveKind::Blend(ref blend) => {
-                    let input_1_task_id = get_task_input(
-                        &blend.input1,
-                        filter_primitives,
-                        render_tasks,
-                        cur_index,
-                        &outputs,
-                        original_task_id,
-                        primitive.color_space
-                    );
-                    let input_2_task_id = get_task_input(
-                        &blend.input2,
-                        filter_primitives,
-                        render_tasks,
-                        cur_index,
-                        &outputs,
-                        original_task_id,
-                        primitive.color_space
-                    );
-
-                    let task = RenderTask::new_svg_filter_primitive(
-                        vec![input_1_task_id, input_2_task_id],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::Blend(blend.mode),
-                    );
-                    render_tasks.add(task)
-                },
-                FilterPrimitiveKind::Flood(ref flood) => {
-                    let task = RenderTask::new_svg_filter_primitive(
-                        vec![],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::Flood(flood.color),
-                    );
-                    render_tasks.add(task)
-                }
-                FilterPrimitiveKind::Blur(ref blur) => {
-                    let blur_std_deviation = blur.radius * device_pixel_scale.0;
-                    let input_task_id = get_task_input(
-                        &blur.input,
-                        filter_primitives,
-                        render_tasks,
-                        cur_index,
-                        &outputs,
-                        original_task_id,
-                        primitive.color_space
-                    );
-
-                    // TODO: This is a hack to ensure that a blur task's input is always in the blur's previous pass.
-                    let svg_task = RenderTask::new_svg_filter_primitive(
-                        vec![input_task_id],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::Identity,
-                    );
-
-                    RenderTask::new_blur(
-                        DeviceSize::new(blur_std_deviation, blur_std_deviation),
-                        render_tasks.add(svg_task),
-                        render_tasks,
-                        RenderTargetKind::Color,
-                        ClearMode::Transparent,
-                        None,
-                    )
-                }
-                FilterPrimitiveKind::Opacity(ref opacity) => {
-                    let input_task_id = get_task_input(
-                        &opacity.input,
-                        filter_primitives,
-                        render_tasks,
-                        cur_index,
-                        &outputs,
-                        original_task_id,
-                        primitive.color_space
-                    );
-
-                    let task = RenderTask::new_svg_filter_primitive(
-                        vec![input_task_id],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::Opacity(opacity.opacity),
-                    );
-                    render_tasks.add(task)
-                }
-                FilterPrimitiveKind::ColorMatrix(ref color_matrix) => {
-                    let input_task_id = get_task_input(
-                        &color_matrix.input,
-                        filter_primitives,
-                        render_tasks,
-                        cur_index,
-                        &outputs,
-                        original_task_id,
-                        primitive.color_space
-                    );
-
-                    let task = RenderTask::new_svg_filter_primitive(
-                        vec![input_task_id],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::ColorMatrix(Box::new(color_matrix.matrix)),
-                    );
-                    render_tasks.add(task)
-                }
-                FilterPrimitiveKind::DropShadow(ref drop_shadow) => {
-                    let input_task_id = get_task_input(
-                        &drop_shadow.input,
-                        filter_primitives,
-                        render_tasks,
-                        cur_index,
-                        &outputs,
-                        original_task_id,
-                        primitive.color_space
-                    );
-
-                    let blur_std_deviation = drop_shadow.shadow.blur_radius * device_pixel_scale.0;
-                    let offset = drop_shadow.shadow.offset * LayoutToWorldScale::new(1.0) * device_pixel_scale;
-
-                    let offset_task = RenderTask::new_svg_filter_primitive(
-                        vec![input_task_id],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::Offset(offset),
-                    );
-                    let offset_task_id = render_tasks.add(offset_task);
-
-                    let blur_task_id = RenderTask::new_blur(
-                        DeviceSize::new(blur_std_deviation, blur_std_deviation),
-                        offset_task_id,
-                        render_tasks,
-                        RenderTargetKind::Color,
-                        ClearMode::Transparent,
-                        None,
-                    );
-
-                    let task = RenderTask::new_svg_filter_primitive(
-                        vec![input_task_id, blur_task_id],
-                        content_size,
-                        uv_rect_kind,
-                        SvgFilterInfo::DropShadow(drop_shadow.shadow.color),
-                    );
-                    render_tasks.add(task)
-                }
-                FilterPrimitiveKind::ComponentTransfer(ref component_transfer) => {
-                    let input_task_id = get_task_input(
-                        &component_transfer.input,
-                        filter_primitives,
-                        render_tasks,
-                        cur_index,
-                        &outputs,
-                        original_task_id,
-                        primitive.color_space
-                    );
-
-                    let filter_data = &filter_datas[cur_filter_data];
-                    cur_filter_data += 1;
-                    if filter_data.is_identity() {
-                        input_task_id
-                    } else {
-                        let task = RenderTask::new_svg_filter_primitive(
-                            vec![input_task_id],
-                            content_size,
-                            uv_rect_kind,
-                            SvgFilterInfo::ComponentTransfer(filter_data.clone()),
-                        );
-                        render_tasks.add(task)
-                    }
-                }
-            };
-            outputs.push(render_task_id);
-        }
-
-        // The output of a filter is the output of the last primitive in the chain.
-        let mut render_task_id = *outputs.last().unwrap();
-
-        // Convert to sRGB if needed
-        if filter_primitives.last().unwrap().color_space == ColorSpace::LinearRgb {
-            let task = RenderTask::new_svg_filter_primitive(
-                vec![render_task_id],
-                content_size,
-                uv_rect_kind,
-                SvgFilterInfo::LinearToSrgb,
-            );
-            render_task_id = render_tasks.add(task);
-        }
-
-        render_task_id
-    }
-
-    pub fn new_svg_filter_primitive(
-        tasks: Vec<RenderTaskId>,
-        target_size: DeviceIntSize,
-        uv_rect_kind: UvRectKind,
-        info: SvgFilterInfo,
-    ) -> Self {
-        RenderTask::with_dynamic_location(
-            target_size,
-            tasks,
-            RenderTaskKind::SvgFilter(SvgFilterTask {
-                extra_gpu_cache_handle: None,
-                uv_rect_handle: GpuCacheHandle::new(),
-                uv_rect_kind,
-                info,
-            }),
-            ClearMode::Transparent,
-        )
-    }
-
     #[cfg(feature = "pathfinder")]
     pub fn new_glyph(
         location: RenderTaskLocation,
         mesh: Mesh,
         origin: &DeviceIntPoint,
         subpixel_offset: &TypedPoint2D<f32, DevicePixel>,
         render_mode: FontRenderMode,
         embolden_amount: &TypedVector2D<f32, DevicePixel>,
@@ -1520,20 +1211,16 @@ impl RenderTask {
             RenderTaskKind::HorizontalBlur(ref task) => {
                 task.uv_rect_kind
             }
 
             RenderTaskKind::Scaling(ref task) => {
                 task.uv_rect_kind
             }
 
-            RenderTaskKind::SvgFilter(ref task) => {
-                task.uv_rect_kind
-            }
-
             RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::Glyph(_) |
             RenderTaskKind::Border(..) |
             RenderTaskKind::Gradient(..) |
             RenderTaskKind::LineDecoration(..) |
             RenderTaskKind::Blit(..) => {
                 UvRectKind::Rect
             }
@@ -1595,25 +1282,16 @@ impl RenderTask {
             RenderTaskKind::Scaling(..) |
             RenderTaskKind::Border(..) |
             RenderTaskKind::LineDecoration(..) |
             RenderTaskKind::Gradient(..) |
             RenderTaskKind::Blit(..) => {
                 [0.0; 3]
             }
 
-
-            RenderTaskKind::SvgFilter(ref task) => {
-                match task.info {
-                    SvgFilterInfo::Opacity(opacity) => [opacity, 0.0, 0.0],
-                    SvgFilterInfo::Offset(offset) => [offset.x, offset.y, 0.0],
-                    _ => [0.0; 3]
-                }
-            }
-
             #[cfg(test)]
             RenderTaskKind::Test(..) => {
                 unreachable!();
             }
         };
 
         let (mut target_rect, target_index) = self.get_target_rect();
         // The primitives inside a fixed-location render task
@@ -1641,19 +1319,16 @@ impl RenderTask {
         match self.kind {
             RenderTaskKind::Picture(ref info) => {
                 gpu_cache.get_address(&info.uv_rect_handle)
             }
             RenderTaskKind::VerticalBlur(ref info) |
             RenderTaskKind::HorizontalBlur(ref info) => {
                 gpu_cache.get_address(&info.uv_rect_handle)
             }
-            RenderTaskKind::SvgFilter(ref info) => {
-                gpu_cache.get_address(&info.uv_rect_handle)
-            }
             RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::Readback(..) |
             RenderTaskKind::Scaling(..) |
             RenderTaskKind::Blit(..) |
             RenderTaskKind::Border(..) |
             RenderTaskKind::CacheMask(..) |
             RenderTaskKind::Gradient(..) |
             RenderTaskKind::LineDecoration(..) |
@@ -1713,41 +1388,48 @@ impl RenderTask {
                     RenderTargetIndex(layer as usize),
                 )
             }
         }
     }
 
     pub fn target_kind(&self) -> RenderTargetKind {
         match self.kind {
-            RenderTaskKind::LineDecoration(..) |
-            RenderTaskKind::Readback(..) |
-            RenderTaskKind::Glyph(..) |
-            RenderTaskKind::Border(..) |
-            RenderTaskKind::Gradient(..) |
-            RenderTaskKind::Picture(..) |
-            RenderTaskKind::Blit(..) |
-            RenderTaskKind::SvgFilter(..) => {
-                RenderTargetKind::Color
-            }
+            RenderTaskKind::Readback(..) => RenderTargetKind::Color,
+
+            RenderTaskKind::LineDecoration(..) => RenderTargetKind::Color,
 
             RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::CacheMask(..) => {
                 RenderTargetKind::Alpha
             }
 
             RenderTaskKind::VerticalBlur(ref task_info) |
             RenderTaskKind::HorizontalBlur(ref task_info) => {
                 task_info.target_kind
             }
 
+            RenderTaskKind::Glyph(..) => {
+                RenderTargetKind::Color
+            }
+
             RenderTaskKind::Scaling(ref task_info) => {
                 task_info.target_kind
             }
 
+            RenderTaskKind::Border(..) |
+            RenderTaskKind::Gradient(..) |
+            RenderTaskKind::Picture(..) => {
+                RenderTargetKind::Color
+            }
+
+            RenderTaskKind::Blit(..) => {
+                RenderTargetKind::Color
+            }
+
             #[cfg(test)]
             RenderTaskKind::Test(kind) => kind,
         }
     }
 
     pub fn write_gpu_blocks(
         &mut self,
         gpu_cache: &mut GpuCache,
@@ -1757,19 +1439,16 @@ impl RenderTask {
         let (cache_handle, uv_rect_kind) = match self.kind {
             RenderTaskKind::HorizontalBlur(ref mut info) |
             RenderTaskKind::VerticalBlur(ref mut info) => {
                 (&mut info.uv_rect_handle, info.uv_rect_kind)
             }
             RenderTaskKind::Picture(ref mut info) => {
                 (&mut info.uv_rect_handle, info.uv_rect_kind)
             }
-            RenderTaskKind::SvgFilter(ref mut info) => {
-                (&mut info.uv_rect_handle, info.uv_rect_kind)
-            }
             RenderTaskKind::Readback(..) |
             RenderTaskKind::Scaling(..) |
             RenderTaskKind::Blit(..) |
             RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::Border(..) |
             RenderTaskKind::CacheMask(..) |
             RenderTaskKind::Gradient(..) |
             RenderTaskKind::LineDecoration(..) |
@@ -1789,43 +1468,16 @@ impl RenderTask {
                 p0,
                 p1,
                 texture_layer: target_index.0 as f32,
                 user_data: [0.0; 3],
                 uv_rect_kind,
             };
             image_source.write_gpu_blocks(&mut request);
         }
-
-        if let RenderTaskKind::SvgFilter(ref mut filter_task) = self.kind {
-            match filter_task.info {
-                SvgFilterInfo::ColorMatrix(ref matrix) => {
-                    let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(|| GpuCacheHandle::new());
-                    if let Some(mut request) = gpu_cache.request(handle) {
-                        for i in 0..5 {
-                            request.push([matrix[i*4], matrix[i*4+1], matrix[i*4+2], matrix[i*4+3]]);
-                        }
-                    }
-                }
-                SvgFilterInfo::DropShadow(color) |
-                SvgFilterInfo::Flood(color) => {
-                    let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(|| GpuCacheHandle::new());
-                    if let Some(mut request) = gpu_cache.request(handle) {
-                        request.push(color.to_array());
-                    }
-                }
-                SvgFilterInfo::ComponentTransfer(ref data) => {
-                    let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(|| GpuCacheHandle::new());
-                    if let Some(request) = gpu_cache.request(handle) {
-                        data.update(request);
-                    }
-                }
-                _ => {},
-            }
-        }
     }
 
     #[cfg(feature = "debugger")]
     pub fn print_with<T: PrintTreePrinter>(&self, pt: &mut T, tree: &RenderTaskGraph) -> bool {
         match self.kind {
             RenderTaskKind::Picture(ref task) => {
                 pt.new_level(format!("Picture of {:?}", task.pic_index));
             }
@@ -1863,28 +1515,23 @@ impl RenderTask {
                 pt.add_item(format!("source: {:?}", task.source));
             }
             RenderTaskKind::Glyph(..) => {
                 pt.new_level("Glyph".to_owned());
             }
             RenderTaskKind::Gradient(..) => {
                 pt.new_level("Gradient".to_owned());
             }
-            RenderTaskKind::SvgFilter(ref task) => {
-                pt.new_level("SvgFilter".to_owned());
-                pt.add_item(format!("primitive: {:?}", task.info));
-            }
             #[cfg(test)]
             RenderTaskKind::Test(..) => {
                 pt.new_level("Test".to_owned());
             }
         }
 
         pt.add_item(format!("clear to: {:?}", self.clear_mode));
-        pt.add_item(format!("dimensions: {:?}", self.location.size()));
 
         for &child_id in &self.children {
             if tree[child_id].print_with(pt, tree) {
                 pt.add_item(format!("self: {:?}", child_id))
             }
         }
 
         pt.end_level();
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -58,17 +58,17 @@ use crate::device::query::GpuTimer;
 use euclid::{rect, Transform3D, TypedScale};
 use crate::frame_builder::{ChasePrimitive, FrameBuilderConfig};
 use gleam::gl;
 use crate::glyph_rasterizer::{GlyphFormat, GlyphRasterizer};
 use crate::gpu_cache::{GpuBlockData, GpuCacheUpdate, GpuCacheUpdateList};
 use crate::gpu_cache::{GpuCacheDebugChunk, GpuCacheDebugCmd};
 #[cfg(feature = "pathfinder")]
 use crate::gpu_glyph_renderer::GpuGlyphRenderer;
-use crate::gpu_types::{PrimitiveHeaderI, PrimitiveHeaderF, ScalingInstance, SvgFilterInstance, TransformData, ResolveInstanceData};
+use crate::gpu_types::{PrimitiveHeaderI, PrimitiveHeaderF, ScalingInstance, TransformData, ResolveInstanceData};
 use crate::internal_types::{TextureSource, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceCacheError};
 use crate::internal_types::{CacheTextureId, DebugOutput, FastHashMap, FastHashSet, LayerIndex, RenderedDocument, ResultMsg};
 use crate::internal_types::{TextureCacheAllocationKind, TextureCacheUpdate, TextureUpdateList, TextureUpdateSource};
 use crate::internal_types::{RenderTargetInfo, SavedTargetIndex};
 use malloc_size_of::MallocSizeOfOps;
 use crate::picture::{RecordedDirtyRegion, TILE_SIZE_WIDTH, TILE_SIZE_HEIGHT};
 use crate::prim_store::DeferredResolve;
 use crate::profiler::{BackendProfileCounters, FrameProfileCounters, TimeProfileCounter,
@@ -215,20 +215,16 @@ const GPU_SAMPLER_TAG_ALPHA: GpuProfileT
 const GPU_SAMPLER_TAG_OPAQUE: GpuProfileTag = GpuProfileTag {
     label: "Opaque Pass",
     color: debug_colors::BLACK,
 };
 const GPU_SAMPLER_TAG_TRANSPARENT: GpuProfileTag = GpuProfileTag {
     label: "Transparent Pass",
     color: debug_colors::BLACK,
 };
-const GPU_TAG_SVG_FILTER: GpuProfileTag = GpuProfileTag {
-    label: "SvgFilter",
-    color: debug_colors::LEMONCHIFFON,
-};
 
 /// The clear color used for the texture cache when the debug display is enabled.
 /// We use a shade of blue so that we can still identify completely blue items in
 /// the texture cache.
 const TEXTURE_CACHE_DBG_CLEAR_COLOR: [f32; 4] = [0.0, 0.0, 0.8, 1.0];
 
 impl BatchKind {
     #[cfg(feature = "debugger")]
@@ -661,63 +657,16 @@ pub(crate) mod desc {
             VertexAttribute {
                 name: "aRect",
                 count: 4,
                 kind: VertexAttributeKind::F32,
             },
         ],
     };
 
-    pub const SVG_FILTER: VertexDescriptor = VertexDescriptor {
-        vertex_attributes: &[
-            VertexAttribute {
-                name: "aPosition",
-                count: 2,
-                kind: VertexAttributeKind::F32,
-            },
-        ],
-        instance_attributes: &[
-            VertexAttribute {
-                name: "aFilterRenderTaskAddress",
-                count: 1,
-                kind: VertexAttributeKind::U16,
-            },
-            VertexAttribute {
-                name: "aFilterInput1TaskAddress",
-                count: 1,
-                kind: VertexAttributeKind::U16,
-            },
-            VertexAttribute {
-                name: "aFilterInput2TaskAddress",
-                count: 1,
-                kind: VertexAttributeKind::U16,
-            },
-            VertexAttribute {
-                name: "aFilterKind",
-                count: 1,
-                kind: VertexAttributeKind::U16,
-            },
-            VertexAttribute {
-                name: "aFilterInputCount",
-                count: 1,
-                kind: VertexAttributeKind::U16,
-            },
-            VertexAttribute {
-                name: "aFilterGenericInt",
-                count: 1,
-                kind: VertexAttributeKind::U16,
-            },
-            VertexAttribute {
-                name: "aFilterExtraDataAddress",
-                count: 2,
-                kind: VertexAttributeKind::U16,
-            },
-        ],
-    };
-
     pub const VECTOR_STENCIL: VertexDescriptor = VertexDescriptor {
         vertex_attributes: &[
             VertexAttribute {
                 name: "aPosition",
                 count: 2,
                 kind: VertexAttributeKind::F32,
             },
         ],
@@ -805,17 +754,16 @@ pub(crate) enum VertexArrayKind {
     Clip,
     VectorStencil,
     VectorCover,
     Border,
     Scale,
     LineDecoration,
     Gradient,
     Resolve,
-    SvgFilter,
 }
 
 #[derive(Clone, Debug, PartialEq)]
 pub enum GraphicsApi {
     OpenGL,
 }
 
 #[derive(Clone, Debug)]
@@ -1099,35 +1047,18 @@ impl TextureResolver {
                     .expect(&format!("BUG: External image should be resolved by now"));
                 device.bind_external_texture(sampler, texture);
             }
             TextureSource::TextureCache(index) => {
                 let texture = &self.texture_cache_map[&index];
                 device.bind_texture(sampler, texture);
             }
             TextureSource::RenderTaskCache(saved_index) => {
-                if saved_index.0 < self.saved_targets.len() {
-                    let texture = &self.saved_targets[saved_index.0];
-                    device.bind_texture(sampler, texture)
-                } else {
-                    // Check if this saved index is referring to a the prev pass
-                    if Some(saved_index) == self.prev_pass_color.as_ref().and_then(|at| at.saved_index) {
-                        let texture = match self.prev_pass_color {
-                            Some(ref at) => &at.texture,
-                            None => &self.dummy_cache_texture,
-                        };
-                        device.bind_texture(sampler, texture);
-                    } else if Some(saved_index) == self.prev_pass_color.as_ref().and_then(|at| at.saved_index) {
-                        let texture = match self.prev_pass_alpha {
-                            Some(ref at) => &at.texture,
-                            None => &self.dummy_cache_texture,
-                        };
-                        device.bind_texture(sampler, texture);
-                    }
-                }
+                let texture = &self.saved_targets[saved_index.0];
+                device.bind_texture(sampler, texture)
             }
         }
     }
 
     // Get the real (OpenGL) texture ID for a given source texture.
     // For a texture cache texture, the IDs are stored in a vector
     // map for fast access.
     fn resolve(&self, texture_id: &TextureSource) -> Option<&Texture> {
@@ -1656,17 +1587,16 @@ pub struct RendererVAOs {
     prim_vao: VAO,
     blur_vao: VAO,
     clip_vao: VAO,
     border_vao: VAO,
     line_vao: VAO,
     scale_vao: VAO,
     gradient_vao: VAO,
     resolve_vao: VAO,
-    svg_filter_vao: VAO,
 }
 
 
 /// The renderer is responsible for submitting to the GPU the work prepared by the
 /// RenderBackend.
 ///
 /// We have a separate `Renderer` instance for each instance of WebRender (generally
 /// one per OS window), and all instances share the same thread.
@@ -2004,17 +1934,16 @@ impl Renderer {
 
         let blur_vao = device.create_vao_with_new_instances(&desc::BLUR, &prim_vao);
         let clip_vao = device.create_vao_with_new_instances(&desc::CLIP, &prim_vao);
         let border_vao = device.create_vao_with_new_instances(&desc::BORDER, &prim_vao);
         let scale_vao = device.create_vao_with_new_instances(&desc::SCALE, &prim_vao);
         let line_vao = device.create_vao_with_new_instances(&desc::LINE, &prim_vao);
         let gradient_vao = device.create_vao_with_new_instances(&desc::GRADIENT, &prim_vao);
         let resolve_vao = device.create_vao_with_new_instances(&desc::RESOLVE, &prim_vao);
-        let svg_filter_vao = device.create_vao_with_new_instances(&desc::SVG_FILTER, &prim_vao);
         let texture_cache_upload_pbo = device.create_pbo();
 
         let texture_resolver = TextureResolver::new(&mut device);
 
         let prim_header_f_texture = VertexDataTexture::new(&mut device, ImageFormat::RGBAF32);
         let prim_header_i_texture = VertexDataTexture::new(&mut device, ImageFormat::RGBAI32);
         let transforms_texture = VertexDataTexture::new(&mut device, ImageFormat::RGBAF32);
         let render_task_texture = VertexDataTexture::new(&mut device, ImageFormat::RGBAF32);
@@ -2235,17 +2164,16 @@ impl Renderer {
                 prim_vao,
                 blur_vao,
                 clip_vao,
                 border_vao,
                 scale_vao,
                 gradient_vao,
                 resolve_vao,
                 line_vao,
-                svg_filter_vao,
             },
             transforms_texture,
             prim_header_i_texture,
             prim_header_f_texture,
             render_task_texture,
             pipeline_info: PipelineInfo::default(),
             dither_matrix_texture,
             external_image_handler: None,
@@ -2578,21 +2506,16 @@ impl Renderer {
             "Vertical Blur",
             target.vertical_blurs.len(),
         );
         debug_target.add(
             debug_server::BatchKind::Cache,
             "Horizontal Blur",
             target.horizontal_blurs.len(),
         );
-        debug_target.add(
-            debug_server::BatchKind::Cache,
-            "SVG Filters",
-            target.svg_filters.iter().map(|(_, batch)| batch.len()).sum(),
-        );
 
         for alpha_batch_container in &target.alpha_batch_containers {
             for batch in alpha_batch_container.opaque_batches.iter().rev() {
                 debug_target.add(
                     debug_server::BatchKind::Opaque,
                     batch.key.kind.debug_name(),
                     batch.instances.len(),
                 );
@@ -3447,43 +3370,16 @@ impl Renderer {
         self.draw_instanced_batch(
             &scalings,
             VertexArrayKind::Scale,
             &BatchTextures::color(source),
             stats,
         );
     }
 
-    fn handle_svg_filters(
-        &mut self,
-        textures: &BatchTextures,
-        svg_filters: &[SvgFilterInstance],
-        projection: &Transform3D<f32>,
-        stats: &mut RendererStats,
-    ) {
-        if svg_filters.is_empty() {
-            return;
-        }
-
-        let _timer = self.gpu_profile.start_timer(GPU_TAG_SVG_FILTER);
-
-        self.shaders.borrow_mut().cs_svg_filter.bind(
-            &mut self.device,
-            &projection,
-            &mut self.renderer_errors
-        );
-
-        self.draw_instanced_batch(
-            &svg_filters,
-            VertexArrayKind::SvgFilter,
-            textures,
-            stats,
-        );
-    }
-
     fn draw_picture_cache_target(
         &mut self,
         target: &PictureCacheTarget,
         draw_target: DrawTarget,
         content_origin: DeviceIntPoint,
         projection: &Transform3D<f32>,
         render_tasks: &RenderTaskGraph,
         stats: &mut RendererStats,
@@ -3842,25 +3738,16 @@ impl Renderer {
 
         self.handle_scaling(
             &target.scalings,
             TextureSource::PrevPassColor,
             projection,
             stats,
         );
 
-        for (ref textures, ref filters) in &target.svg_filters {
-            self.handle_svg_filters(
-                textures,
-                filters,
-                projection,
-                stats,
-            );
-        }
-
         for alpha_batch_container in &target.alpha_batch_containers {
             self.draw_alpha_batch_container(
                 alpha_batch_container,
                 draw_target,
                 content_origin,
                 framebuffer_kind,
                 projection,
                 render_tasks,
@@ -5222,17 +5109,16 @@ impl Renderer {
         self.device.delete_vao(self.vaos.prim_vao);
         self.device.delete_vao(self.vaos.resolve_vao);
         self.device.delete_vao(self.vaos.clip_vao);
         self.device.delete_vao(self.vaos.gradient_vao);
         self.device.delete_vao(self.vaos.blur_vao);
         self.device.delete_vao(self.vaos.line_vao);
         self.device.delete_vao(self.vaos.border_vao);
         self.device.delete_vao(self.vaos.scale_vao);
-        self.device.delete_vao(self.vaos.svg_filter_vao);
 
         self.debug.deinit(&mut self.device);
 
         for (_, target) in self.output_targets {
             self.device.delete_fbo(target.fbo_id);
         }
         if let Ok(shaders) = Rc::try_unwrap(self.shaders) {
             shaders.into_inner().deinit(&mut self.device);
@@ -6046,17 +5932,16 @@ fn get_vao<'a>(vertex_array_kind: Vertex
         VertexArrayKind::Blur => &vaos.blur_vao,
         VertexArrayKind::VectorStencil => &gpu_glyph_renderer.vector_stencil_vao,
         VertexArrayKind::VectorCover => &gpu_glyph_renderer.vector_cover_vao,
         VertexArrayKind::Border => &vaos.border_vao,
         VertexArrayKind::Scale => &vaos.scale_vao,
         VertexArrayKind::LineDecoration => &vaos.line_vao,
         VertexArrayKind::Gradient => &vaos.gradient_vao,
         VertexArrayKind::Resolve => &vaos.resolve_vao,
-        VertexArrayKind::SvgFilter => &vaos.svg_filter_vao,
     }
 }
 
 #[cfg(not(feature = "pathfinder"))]
 fn get_vao<'a>(vertex_array_kind: VertexArrayKind,
                vaos: &'a RendererVAOs,
                _: &'a GpuGlyphRenderer)
                -> &'a VAO {
@@ -6065,17 +5950,16 @@ fn get_vao<'a>(vertex_array_kind: Vertex
         VertexArrayKind::Clip => &vaos.clip_vao,
         VertexArrayKind::Blur => &vaos.blur_vao,
         VertexArrayKind::VectorStencil | VertexArrayKind::VectorCover => unreachable!(),
         VertexArrayKind::Border => &vaos.border_vao,
         VertexArrayKind::Scale => &vaos.scale_vao,
         VertexArrayKind::LineDecoration => &vaos.line_vao,
         VertexArrayKind::Gradient => &vaos.gradient_vao,
         VertexArrayKind::Resolve => &vaos.resolve_vao,
-        VertexArrayKind::SvgFilter => &vaos.svg_filter_vao,
     }
 }
 #[derive(Clone, Copy, PartialEq)]
 enum FramebufferKind {
     Main,
     Other,
 }
 
--- a/gfx/wr/webrender/src/scene.rs
+++ b/gfx/wr/webrender/src/scene.rs
@@ -1,14 +1,14 @@
 /* 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/. */
 
 use api::{BuiltDisplayList, ColorF, DynamicProperties, Epoch};
-use api::{FilterOp, TempFilterData, FilterData, FilterPrimitive, ComponentTransferFuncType};
+use api::{FilterOp, TempFilterData, FilterData, ComponentTransferFuncType};
 use api::{PipelineId, PropertyBinding, PropertyBindingId, ItemRange, MixBlendMode, StackingContext};
 use api::units::{LayoutSize, LayoutTransform};
 use crate::internal_types::{FastHashMap, Filter};
 use std::sync::Arc;
 
 /// Stores a map of the animated property bindings for the current display list. These
 /// can be used to animate the transform and/or opacity of a display list without
 /// re-submitting the display list itself.
@@ -201,20 +201,16 @@ pub trait StackingContextHelpers {
     fn filter_ops_for_compositing(
         &self,
         input_filters: ItemRange<FilterOp>,
     ) -> Vec<Filter>;
     fn filter_datas_for_compositing(
         &self,
         input_filter_datas: &[TempFilterData],
     ) -> Vec<FilterData>;
-    fn filter_primitives_for_compositing(
-        &self,
-        input_filter_primitives: ItemRange<FilterPrimitive>,
-    ) -> Vec<FilterPrimitive>;
 }
 
 impl StackingContextHelpers for StackingContext {
     fn mix_blend_mode_for_compositing(&self) -> Option<MixBlendMode> {
         match self.mix_blend_mode {
             MixBlendMode::Normal => None,
             _ => Some(self.mix_blend_mode),
         }
@@ -253,20 +249,9 @@ impl StackingContextHelpers for Stacking
                 func_b_type: func_types[2],
                 b_values: temp_filter_data.b_values.iter().collect(),
                 func_a_type: func_types[3],
                 a_values: temp_filter_data.a_values.iter().collect(),
             });
         }
         filter_datas
     }
-
-    fn filter_primitives_for_compositing(
-        &self,
-        input_filter_primitives: ItemRange<FilterPrimitive>,
-    ) -> Vec<FilterPrimitive> {
-        // Resolve these in the flattener?
-        // TODO(gw): Now that we resolve these later on,
-        //           we could probably make it a bit
-        //           more efficient than cloning these here.
-        input_filter_primitives.iter().map(|primitive| primitive.into()).collect()
-    }
 }
--- a/gfx/wr/webrender/src/shade.rs
+++ b/gfx/wr/webrender/src/shade.rs
@@ -187,17 +187,16 @@ impl LazilyCompiledShader {
                 VertexArrayKind::Gradient => &desc::GRADIENT,
                 VertexArrayKind::Blur => &desc::BLUR,
                 VertexArrayKind::Clip => &desc::CLIP,
                 VertexArrayKind::VectorStencil => &desc::VECTOR_STENCIL,
                 VertexArrayKind::VectorCover => &desc::VECTOR_COVER,
                 VertexArrayKind::Border => &desc::BORDER,
                 VertexArrayKind::Scale => &desc::SCALE,
                 VertexArrayKind::Resolve => &desc::RESOLVE,
-                VertexArrayKind::SvgFilter => &desc::SVG_FILTER,
             };
 
             device.link_program(program, vertex_descriptor)?;
             device.bind_program(program);
             match self.kind {
                 ShaderKind::ClipCache => {
                     device.bind_shader_samplers(
                         &program,
@@ -507,17 +506,16 @@ pub struct Shaders {
     // of these shaders are then used by the primitive shaders.
     pub cs_blur_a8: LazilyCompiledShader,
     pub cs_blur_rgba8: LazilyCompiledShader,
     pub cs_border_segment: LazilyCompiledShader,
     pub cs_border_solid: LazilyCompiledShader,
     pub cs_scale: LazilyCompiledShader,
     pub cs_line_decoration: LazilyCompiledShader,
     pub cs_gradient: LazilyCompiledShader,
-    pub cs_svg_filter: LazilyCompiledShader,
 
     // Brush shaders
     brush_solid: BrushShader,
     brush_image: Vec<Option<BrushShader>>,
     brush_fast_image: Vec<Option<BrushShader>>,
     brush_blend: BrushShader,
     brush_mix_blend: BrushShader,
     brush_yuv_image: Vec<Option<BrushShader>>,
@@ -630,24 +628,16 @@ impl Shaders {
         let cs_blur_rgba8 = LazilyCompiledShader::new(
             ShaderKind::Cache(VertexArrayKind::Blur),
             "cs_blur",
             &["COLOR_TARGET"],
             device,
             options.precache_flags,
         )?;
 
-        let cs_svg_filter = LazilyCompiledShader::new(
-            ShaderKind::Cache(VertexArrayKind::SvgFilter),
-            "cs_svg_filter",
-            &[],
-            device,
-            options.precache_flags,
-        )?;
-
         let cs_clip_rectangle_slow = LazilyCompiledShader::new(
             ShaderKind::ClipCache,
             "cs_clip_rectangle",
             &[],
             device,
             options.precache_flags,
         )?;
 
@@ -851,17 +841,16 @@ impl Shaders {
         Ok(Shaders {
             cs_blur_a8,
             cs_blur_rgba8,
             cs_border_segment,
             cs_line_decoration,
             cs_gradient,
             cs_border_solid,
             cs_scale,
-            cs_svg_filter,
             brush_solid,
             brush_image,
             brush_fast_image,
             brush_blend,
             brush_mix_blend,
             brush_yuv_image,
             brush_radial_gradient,
             brush_linear_gradient,
@@ -936,17 +925,16 @@ impl Shaders {
             }
         }
     }
 
     pub fn deinit(self, device: &mut Device) {
         self.cs_scale.deinit(device);
         self.cs_blur_a8.deinit(device);
         self.cs_blur_rgba8.deinit(device);
-        self.cs_svg_filter.deinit(device);
         self.brush_solid.deinit(device);
         self.brush_blend.deinit(device);
         self.brush_mix_blend.deinit(device);
         self.brush_radial_gradient.deinit(device);
         self.brush_linear_gradient.deinit(device);
         self.cs_clip_rectangle_slow.deinit(device);
         self.cs_clip_rectangle_fast.deinit(device);
         self.cs_clip_box_shadow.deinit(device);
--- a/gfx/wr/webrender/src/tiling.rs
+++ b/gfx/wr/webrender/src/tiling.rs
@@ -1,37 +1,37 @@
 /* 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/. */
 
-use api::{ColorF, BorderStyle, FilterPrimitive, MixBlendMode, PipelineId, PremultipliedColorF};
+use api::{ColorF, BorderStyle, MixBlendMode, PipelineId, PremultipliedColorF};
 use api::{DocumentLayer, FilterData, ImageFormat, LineOrientation};
 use api::units::*;
 #[cfg(feature = "pathfinder")]
 use api::FontRenderMode;
-use crate::batch::{AlphaBatchBuilder, AlphaBatchContainer, BatchTextures, ClipBatcher, resolve_image, BatchBuilder};
+use crate::batch::{AlphaBatchBuilder, AlphaBatchContainer, ClipBatcher, resolve_image, BatchBuilder};
 use crate::clip::ClipStore;
 use crate::clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX};
 use crate::debug_render::DebugItem;
 use crate::device::{Texture};
 #[cfg(feature = "pathfinder")]
 use euclid::{TypedPoint2D, TypedVector2D};
 use crate::frame_builder::FrameGlobalResources;
-use crate::gpu_cache::{GpuCache, GpuCacheAddress};
-use crate::gpu_types::{BorderInstance, SvgFilterInstance, BlurDirection, BlurInstance, PrimitiveHeaders, ScalingInstance};
+use crate::gpu_cache::{GpuCache};
+use crate::gpu_types::{BorderInstance, BlurDirection, BlurInstance, PrimitiveHeaders, ScalingInstance};
 use crate::gpu_types::{TransformData, TransformPalette, ZBufferIdGenerator};
 use crate::internal_types::{CacheTextureId, FastHashMap, SavedTargetIndex, TextureSource, Filter};
 #[cfg(feature = "pathfinder")]
 use pathfinder_partitioner::mesh::Mesh;
 use crate::picture::{RecordedDirtyRegion, SurfaceInfo};
 use crate::prim_store::gradient::GRADIENT_FP_STOPS;
 use crate::prim_store::{PrimitiveStore, DeferredResolve, PrimitiveScratchBuffer, PrimitiveVisibilityMask};
 use crate::profiler::FrameProfileCounters;
 use crate::render_backend::{DataStores, FrameId};
-use crate::render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind, SvgFilterTask, SvgFilterInfo};
+use crate::render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
 use crate::render_task::{BlurTask, ClearMode, GlyphTask, RenderTaskLocation, RenderTaskGraph, ScalingTask};
 use crate::resource_cache::ResourceCache;
 use std::{cmp, usize, f32, i32, mem};
 use crate::texture_allocator::{ArrayAllocationTracker, FreeRectSlice};
 
 
 const STYLE_SOLID: i32 = ((BorderStyle::Solid as i32) << 8) | ((BorderStyle::Solid as i32) << 16);
 const STYLE_MASK: i32 = 0x00FF_FF00;
@@ -356,17 +356,16 @@ pub struct GlyphJob;
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct ColorRenderTarget {
     pub alpha_batch_containers: Vec<AlphaBatchContainer>,
     // List of blur operations to apply for this render target.
     pub vertical_blurs: Vec<BlurInstance>,
     pub horizontal_blurs: Vec<BlurInstance>,
     pub readbacks: Vec<DeviceIntRect>,
     pub scalings: Vec<ScalingInstance>,
-    pub svg_filters: Vec<(BatchTextures, Vec<SvgFilterInstance>)>,
     pub blits: Vec<BlitJob>,
     // List of frame buffer outputs for this render target.
     pub outputs: Vec<FrameOutput>,
     alpha_tasks: Vec<RenderTaskId>,
     screen_size: DeviceIntSize,
     // Track the used rect of the render target, so that
     // we can set a scissor rect and only clear to the
     // used portion of the target as an optimization.
@@ -379,17 +378,16 @@ impl RenderTarget for ColorRenderTarget 
         _: bool,
     ) -> Self {
         ColorRenderTarget {
             alpha_batch_containers: Vec::new(),
             vertical_blurs: Vec::new(),
             horizontal_blurs: Vec::new(),
             readbacks: Vec::new(),
             scalings: Vec::new(),
-            svg_filters: Vec::new(),
             blits: Vec::new(),
             outputs: Vec::new(),
             alpha_tasks: Vec::new(),
             screen_size,
             used_rect: DeviceIntRect::zero(),
         }
     }
 
@@ -530,27 +528,16 @@ impl RenderTarget for ColorRenderTarget 
                 // store the information necessary to do the copy.
                 if let Some(pipeline_id) = pic.frame_output_pipeline_id {
                     self.outputs.push(FrameOutput {
                         pipeline_id,
                         task_id,
                     });
                 }
             }
-            RenderTaskKind::SvgFilter(ref task_info) => {
-                task_info.add_instances(
-                    &mut self.svg_filters,
-                    render_tasks,
-                    &task_info.info,
-                    task_id,
-                    task.children.get(0).cloned(),
-                    task.children.get(1).cloned(),
-                    task_info.extra_gpu_cache_handle.map(|handle| gpu_cache.get_address(&handle)),
-                )
-            }
             RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::Border(..) |
             RenderTaskKind::CacheMask(..) |
             RenderTaskKind::Gradient(..) |
             RenderTaskKind::LineDecoration(..) => {
                 panic!("Should not be added to color target!");
             }
             RenderTaskKind::Glyph(..) => {
@@ -694,18 +681,17 @@ impl RenderTarget for AlphaRenderTarget 
 
         match task.kind {
             RenderTaskKind::Readback(..) |
             RenderTaskKind::Picture(..) |
             RenderTaskKind::Blit(..) |
             RenderTaskKind::Border(..) |
             RenderTaskKind::LineDecoration(..) |
             RenderTaskKind::Gradient(..) |
-            RenderTaskKind::Glyph(..) |
-            RenderTaskKind::SvgFilter(..) => {
+            RenderTaskKind::Glyph(..) => {
                 panic!("BUG: should not be added to alpha target!");
             }
             RenderTaskKind::VerticalBlur(ref info) => {
                 info.add_instances(
                     &mut self.vertical_blurs,
                     BlurDirection::Vertical,
                     render_tasks.get_task_address(task_id),
                     render_tasks.get_task_address(task.children[0]),
@@ -905,18 +891,17 @@ impl TextureCacheRenderTarget {
                     start_stop: [task_info.start_point, task_info.end_point],
                 });
             }
             RenderTaskKind::VerticalBlur(..) |
             RenderTaskKind::Picture(..) |
             RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::CacheMask(..) |
             RenderTaskKind::Readback(..) |
-            RenderTaskKind::Scaling(..) |
-            RenderTaskKind::SvgFilter(..) => {
+            RenderTaskKind::Scaling(..) => {
                 panic!("BUG: unexpected task kind for texture cache target");
             }
             #[cfg(test)]
             RenderTaskKind::Test(..) => {}
         }
     }
 
     #[cfg(feature = "pathfinder")]
@@ -1342,33 +1327,28 @@ impl RenderPass {
     }
 }
 
 #[derive(Debug, Clone, Default)]
 pub struct CompositeOps {
     // Requires only a single texture as input (e.g. most filters)
     pub filters: Vec<Filter>,
     pub filter_datas: Vec<FilterData>,
-    pub filter_primitives: Vec<FilterPrimitive>,
 
     // Requires two source textures (e.g. mix-blend-mode)
     pub mix_blend_mode: Option<MixBlendMode>,
 }
 
 impl CompositeOps {
-    pub fn new(
-        filters: Vec<Filter>,
-        filter_datas: Vec<FilterData>,
-        filter_primitives: Vec<FilterPrimitive>,
-        mix_blend_mode: Option<MixBlendMode>
-    ) -> Self {
+    pub fn new(filters: Vec<Filter>,
+               filter_datas: Vec<FilterData>,
+               mix_blend_mode: Option<MixBlendMode>) -> Self {
         CompositeOps {
             filters,
             filter_datas,
-            filter_primitives,
             mix_blend_mode,
         }
     }
 
     pub fn is_empty(&self) -> bool {
         self.filters.is_empty() && self.filter_datas.is_empty() && self.mix_blend_mode.is_none()
     }
 }
@@ -1454,105 +1434,8 @@ impl ScalingTask {
         let instance = ScalingInstance {
             task_address,
             src_task_address,
         };
 
         instances.push(instance);
     }
 }
-
-impl SvgFilterTask {
-    fn add_instances(
-        &self,
-        instances: &mut Vec<(BatchTextures, Vec<SvgFilterInstance>)>,
-        render_tasks: &RenderTaskGraph,
-        filter: &SvgFilterInfo,
-        task_id: RenderTaskId,
-        input_1_task: Option<RenderTaskId>,
-        input_2_task: Option<RenderTaskId>,
-        extra_data_address: Option<GpuCacheAddress>,
-    ) {
-        let mut textures = BatchTextures::no_texture();
-
-        if let Some(saved_index) = input_1_task.map(|id| &render_tasks[id].saved_index) {
-            textures.colors[0] = match saved_index {
-                Some(saved_index) => TextureSource::RenderTaskCache(*saved_index),
-                None => TextureSource::PrevPassColor,
-            };
-        }
-
-        if let Some(saved_index) = input_2_task.map(|id| &render_tasks[id].saved_index) {
-            textures.colors[1] = match saved_index {
-                Some(saved_index) => TextureSource::RenderTaskCache(*saved_index),
-                None => TextureSource::PrevPassColor,
-            };
-        }
-
-        let kind = match filter {
-            SvgFilterInfo::Blend(..) => 0,
-            SvgFilterInfo::Flood(..) => 1,
-            SvgFilterInfo::LinearToSrgb => 2,
-            SvgFilterInfo::SrgbToLinear => 3,
-            SvgFilterInfo::Opacity(..) => 4,
-            SvgFilterInfo::ColorMatrix(..) => 5,
-            SvgFilterInfo::DropShadow(..) => 6,
-            SvgFilterInfo::Offset(..) => 7,
-            SvgFilterInfo::ComponentTransfer(..) => 8,
-            SvgFilterInfo::Identity => 9,
-        };
-
-        let input_count = match filter {
-            SvgFilterInfo::Flood(..) => 0,
-
-            SvgFilterInfo::LinearToSrgb |
-            SvgFilterInfo::SrgbToLinear |
-            SvgFilterInfo::Opacity(..) |
-            SvgFilterInfo::ColorMatrix(..) |
-            SvgFilterInfo::Offset(..) |
-            SvgFilterInfo::ComponentTransfer(..) |
-            SvgFilterInfo::Identity => 1,
-
-            // Not techincally a 2 input filter, but we have 2 inputs here: original content & blurred content.
-            SvgFilterInfo::DropShadow(..) |
-            SvgFilterInfo::Blend(..) => 2,
-        };
-
-        let generic_int = match filter {
-            SvgFilterInfo::Blend(mode) => *mode as u16,
-            SvgFilterInfo::ComponentTransfer(data) =>
-                ((data.r_func.to_int() << 12 |
-                  data.g_func.to_int() << 8 |
-                  data.b_func.to_int() << 4 |
-                  data.a_func.to_int()) as u16),
-
-            SvgFilterInfo::LinearToSrgb |
-            SvgFilterInfo::SrgbToLinear |
-            SvgFilterInfo::Flood(..) |
-            SvgFilterInfo::Opacity(..) |
-            SvgFilterInfo::ColorMatrix(..) |
-            SvgFilterInfo::DropShadow(..) |
-            SvgFilterInfo::Offset(..) |
-            SvgFilterInfo::Identity => 0,
-        };
-
-        let instance = SvgFilterInstance {
-            task_address: render_tasks.get_task_address(task_id),
-            input_1_task_address: input_1_task.map(|id| render_tasks.get_task_address(id)).unwrap_or(RenderTaskAddress(0)),
-            input_2_task_address: input_2_task.map(|id| render_tasks.get_task_address(id)).unwrap_or(RenderTaskAddress(0)),
-            kind,
-            input_count,
-            generic_int,
-            extra_data_address: extra_data_address.unwrap_or(GpuCacheAddress::INVALID),
-        };
-
-        for (ref mut batch_textures, ref mut batch) in instances.iter_mut() {
-            if let Some(combined_textures) = batch_textures.combine_textures(textures) {
-                batch.push(instance);
-                // Update the batch textures to the newly combined batch textures
-                *batch_textures = combined_textures;
-                return;
-            }
-        }
-
-        instances.push((textures, vec![instance]));
-    }
-}
--- a/gfx/wr/webrender/tests/angle_shader_validation.rs
+++ b/gfx/wr/webrender/tests/angle_shader_validation.rs
@@ -59,20 +59,16 @@ const SHADERS: &[Shader] = &[
     Shader {
         name: "cs_gradient",
         features: CACHE_FEATURES,
     },
     Shader {
         name: "cs_border_solid",
         features: CACHE_FEATURES,
     },
-    Shader {
-        name: "cs_svg_filter",
-        features: CACHE_FEATURES,
-    },
     // Prim shaders
     Shader {
         name: "ps_split_composite",
         features: PRIM_FEATURES,
     },
     Shader {
         name: "ps_text_run",
         features: &[ "", "GLYPH_TRANSFORM" ],
--- a/gfx/wr/webrender_api/src/display_item.rs
+++ b/gfx/wr/webrender_api/src/display_item.rs
@@ -116,17 +116,16 @@ pub enum DisplayItem {
     PushReferenceFrame(ReferenceFrameDisplayListItem),
     PushStackingContext(PushStackingContextDisplayItem),
 
     // These marker items indicate an array of data follows, to be used for the
     // next non-marker item.
     SetGradientStops,
     SetFilterOps,
     SetFilterData,
-    SetFilterPrimitives,
 
     // These marker items terminate a scope introduced by a previous item.
     PopReferenceFrame,
     PopStackingContext,
     PopAllShadows,
 }
 
 /// This is a "complete" version of the DisplayItem, with all implicit trailing
@@ -155,17 +154,16 @@ pub enum DebugDisplayItem {
     StickyFrame(StickyFrameDisplayItem),
     Iframe(IframeDisplayItem),
     PushReferenceFrame(ReferenceFrameDisplayListItem),
     PushStackingContext(PushStackingContextDisplayItem),
 
     SetGradientStops(Vec<GradientStop>),
     SetFilterOps(Vec<FilterOp>),
     SetFilterData(FilterData),
-    SetFilterPrimitives(Vec<FilterPrimitive>),
 
     PopReferenceFrame,
     PopStackingContext,
     PopAllShadows,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct ClipDisplayItem {
@@ -635,17 +633,17 @@ pub struct PushStackingContextDisplayIte
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct StackingContext {
     pub transform_style: TransformStyle,
     pub mix_blend_mode: MixBlendMode,
     pub clip_id: Option<ClipId>,
     pub raster_space: RasterSpace,
     /// True if picture caching should be used on this stacking context.
     pub cache_tiles: bool,
-} // IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive>
+} // IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>
 
 #[repr(u8)]
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum TransformStyle {
     Flat = 0,
     Preserve3D = 1,
 }
 
@@ -674,17 +672,17 @@ impl RasterSpace {
         match *self {
             RasterSpace::Local(scale) => Some(scale),
             RasterSpace::Screen => None,
         }
     }
 }
 
 #[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum MixBlendMode {
     Normal = 0,
     Multiply = 1,
     Screen = 2,
     Overlay = 3,
     Darken = 4,
     Lighten = 5,
     ColorDodge = 6,
@@ -694,182 +692,16 @@ pub enum MixBlendMode {
     Difference = 10,
     Exclusion = 11,
     Hue = 12,
     Saturation = 13,
     Color = 14,
     Luminosity = 15,
 }
 
-/// An input to a SVG filter primitive.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
-pub enum ColorSpace {
-    Srgb,
-    LinearRgb,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
-pub enum FilterPrimitiveInput {
-    /// The input is the original graphic that the filter is being applied to.
-    Original,
-    /// The input is the output of the previous filter primitive in the filter primitive chain.
-    Previous,
-    /// The input is the output of the filter primitive at the given index in the filter primitive chain.
-    OutputOfPrimitiveIndex(usize),
-}
-
-impl FilterPrimitiveInput {
-    /// Gets the index of the input.
-    /// Returns `None` if the source graphic is the input.
-    pub fn to_index(self, cur_index: usize) -> Option<usize> {
-        match self {
-            FilterPrimitiveInput::Previous if cur_index > 0 => Some(cur_index - 1),
-            FilterPrimitiveInput::OutputOfPrimitiveIndex(index) => Some(index),
-            _ => None,
-        }
-    }
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct BlendPrimitive {
-    pub input1: FilterPrimitiveInput,
-    pub input2: FilterPrimitiveInput,
-    pub mode: MixBlendMode,
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct FloodPrimitive {
-    pub color: ColorF,
-}
-
-impl FloodPrimitive {
-    pub fn sanitize(&mut self) {
-        self.color.r = self.color.r.min(1.0).max(0.0);
-        self.color.g = self.color.g.min(1.0).max(0.0);
-        self.color.b = self.color.b.min(1.0).max(0.0);
-        self.color.a = self.color.a.min(1.0).max(0.0);
-    }
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct BlurPrimitive {
-    pub input: FilterPrimitiveInput,
-    pub radius: f32,
-}
-
-impl BlurPrimitive {
-    pub fn sanitize(&mut self) {
-        self.radius = self.radius.min(MAX_BLUR_RADIUS);
-    }
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct OpacityPrimitive {
-    pub input: FilterPrimitiveInput,
-    pub opacity: f32,
-}
-
-impl OpacityPrimitive {
-    pub fn sanitize(&mut self) {
-        self.opacity = self.opacity.min(1.0).max(0.0);
-    }
-}
-
-/// cbindgen:derive-eq=false
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct ColorMatrixPrimitive {
-    pub input: FilterPrimitiveInput,
-    pub matrix: [f32; 20],
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct DropShadowPrimitive {
-    pub input: FilterPrimitiveInput,
-    pub shadow: Shadow,
-}
-
-impl DropShadowPrimitive {
-    pub fn sanitize(&mut self) {
-        self.shadow.blur_radius = self.shadow.blur_radius.min(MAX_BLUR_RADIUS);
-    }
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct ComponentTransferPrimitive {
-    pub input: FilterPrimitiveInput,
-    // Component transfer data is stored in FilterData.
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct IdentityPrimitive {
-    pub input: FilterPrimitiveInput,
-}
-
-/// See: https://github.com/eqrion/cbindgen/issues/9
-/// cbindgen:derive-eq=false
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub enum FilterPrimitiveKind {
-    Identity(IdentityPrimitive),
-    Blend(BlendPrimitive),
-    Flood(FloodPrimitive),
-    Blur(BlurPrimitive),
-    // TODO: Support animated opacity?
-    Opacity(OpacityPrimitive),
-    /// cbindgen:derive-eq=false
-    ColorMatrix(ColorMatrixPrimitive),
-    DropShadow(DropShadowPrimitive),
-    ComponentTransfer(ComponentTransferPrimitive),
-}
-
-impl FilterPrimitiveKind {
-    pub fn sanitize(&mut self) {
-        match self {
-            FilterPrimitiveKind::Flood(flood) => flood.sanitize(),
-            FilterPrimitiveKind::Blur(blur) => blur.sanitize(),
-            FilterPrimitiveKind::Opacity(opacity) => opacity.sanitize(),
-            FilterPrimitiveKind::DropShadow(drop_shadow) => drop_shadow.sanitize(),
-
-            // No sanitization needed.
-            FilterPrimitiveKind::Identity(..) |
-            FilterPrimitiveKind::Blend(..) |
-            FilterPrimitiveKind::ColorMatrix(..) |
-            // Component transfer's filter data is sanitized separately.
-            FilterPrimitiveKind::ComponentTransfer(..) => {}
-        }
-    }
-}
-
-/// SVG Filter Primitive.
-/// See: https://github.com/eqrion/cbindgen/issues/9
-/// cbindgen:derive-eq=false
-#[repr(C)]
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct FilterPrimitive {
-    pub kind: FilterPrimitiveKind,
-    pub color_space: ColorSpace,
-}
-
-impl FilterPrimitive {
-    pub fn sanitize(&mut self) {
-        self.kind.sanitize();
-    }
-}
-
-/// CSS filter.
 #[repr(C)]
 #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
 pub enum FilterOp {
     /// Filter that does no transformation of the colors, needed for
     /// debug purposes only.
     Identity,
     Blur(f32),
     Brightness(f32),
@@ -1325,17 +1157,16 @@ impl DisplayItem {
             DisplayItem::PopAllShadows => "pop_all_shadows",
             DisplayItem::PopReferenceFrame => "pop_reference_frame",
             DisplayItem::PopStackingContext => "pop_stacking_context",
             DisplayItem::PushShadow(..) => "push_shadow",
             DisplayItem::PushReferenceFrame(..) => "push_reference_frame",
             DisplayItem::PushStackingContext(..) => "push_stacking_context",
             DisplayItem::SetFilterOps => "set_filter_ops",
             DisplayItem::SetFilterData => "set_filter_data",
-            DisplayItem::SetFilterPrimitives => "set_filter_primitives",
             DisplayItem::RadialGradient(..) => "radial_gradient",
             DisplayItem::Rectangle(..) => "rectangle",
             DisplayItem::ScrollFrame(..) => "scroll_frame",
             DisplayItem::SetGradientStops => "set_gradient_stops",
             DisplayItem::StickyFrame(..) => "sticky_frame",
             DisplayItem::Text(..) => "text",
             DisplayItem::YuvImage(..) => "yuv_image",
         }
--- a/gfx/wr/webrender_api/src/display_list.rs
+++ b/gfx/wr/webrender_api/src/display_list.rs
@@ -126,17 +126,16 @@ pub struct BuiltDisplayListDescriptor {
 pub struct BuiltDisplayListIter<'a> {
     list: &'a BuiltDisplayList,
     data: &'a [u8],
     cur_item: di::DisplayItem,
     cur_stops: ItemRange<'a, di::GradientStop>,
     cur_glyphs: ItemRange<'a, GlyphInstance>,
     cur_filters: ItemRange<'a, di::FilterOp>,
     cur_filter_data: Vec<TempFilterData<'a>>,
-    cur_filter_primitives: ItemRange<'a, di::FilterPrimitive>,
     cur_clip_chain_items: ItemRange<'a, di::ClipId>,
     cur_complex_clip: ItemRange<'a, di::ComplexClipRegion>,
     peeking: Peek,
     /// Should just be initialized but never populated in release builds
     debug_stats: DebugStats,
 }
 
 /// Internal info used for more detailed analysis of serialized display lists
@@ -293,17 +292,16 @@ impl<'a> BuiltDisplayListIter<'a> {
         BuiltDisplayListIter {
             list,
             data,
             cur_item: di::DisplayItem::PopStackingContext,
             cur_stops: ItemRange::default(),
             cur_glyphs: ItemRange::default(),
             cur_filters: ItemRange::default(),
             cur_filter_data: Vec::new(),
-            cur_filter_primitives: ItemRange::default(),
             cur_clip_chain_items: ItemRange::default(),
             cur_complex_clip: ItemRange::default(),
             peeking: Peek::NotPeeking,
             debug_stats: DebugStats {
                 last_addr: data.as_ptr() as usize,
                 stats: HashMap::default(),
             }
         }
@@ -332,18 +330,17 @@ impl<'a> BuiltDisplayListIter<'a> {
         self.cur_complex_clip = ItemRange::default();
         self.cur_clip_chain_items = ItemRange::default();
 
         loop {
             self.next_raw()?;
             match self.cur_item {
                 SetGradientStops |
                 SetFilterOps |
-                SetFilterData |
-                SetFilterPrimitives => {
+                SetFilterData => {
                     // These are marker items for populating other display items, don't yield them.
                     continue;
                 }
                 _ => {
                     break;
                 }
             }
         }
@@ -389,20 +386,16 @@ impl<'a> BuiltDisplayListIter<'a> {
 
                 let data = *self.cur_filter_data.last().unwrap();
                 self.debug_stats.log_slice("set_filter_data.func_types", &data.func_types);
                 self.debug_stats.log_slice("set_filter_data.r_values", &data.r_values);
                 self.debug_stats.log_slice("set_filter_data.g_values", &data.g_values);
                 self.debug_stats.log_slice("set_filter_data.b_values", &data.b_values);
                 self.debug_stats.log_slice("set_filter_data.a_values", &data.a_values);
             }
-            SetFilterPrimitives => {
-                self.cur_filter_primitives = skip_slice::<di::FilterPrimitive>(&mut self.data);
-                self.debug_stats.log_slice("set_filter_primitives.primitives", &self.cur_filter_primitives);
-            }
             ClipChain(_) => {
                 self.cur_clip_chain_items = skip_slice::<di::ClipId>(&mut self.data);
                 self.debug_stats.log_slice("clip_chain.clip_ids", &self.cur_clip_chain_items);
             }
             Clip(_) | ScrollFrame(_) => {
                 self.cur_complex_clip = skip_slice::<di::ComplexClipRegion>(&mut self.data);
                 let name = if let Clip(_) = self.cur_item {
                     "clip.complex_clips"
@@ -504,20 +497,16 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> {
     pub fn filters(&self) -> ItemRange<di::FilterOp> {
         self.iter.cur_filters
     }
 
     pub fn filter_datas(&self) -> &Vec<TempFilterData> {
         &self.iter.cur_filter_data
     }
 
-    pub fn filter_primitives(&self) -> ItemRange<di::FilterPrimitive> {
-        self.iter.cur_filter_primitives
-    }
-
     pub fn clip_chain_items(&self) -> ItemRange<di::ClipId> {
         self.iter.cur_clip_chain_items
     }
 
     pub fn display_list(&self) -> &BuiltDisplayList {
         self.iter.display_list()
     }
 
@@ -608,19 +597,16 @@ impl Serialize for BuiltDisplayList {
                         func_g_type: func_types[1],
                         g_values: temp_filter_data.g_values.iter().collect(),
                         func_b_type: func_types[2],
                         b_values: temp_filter_data.b_values.iter().collect(),
                         func_a_type: func_types[3],
                         a_values: temp_filter_data.a_values.iter().collect(),
                     })
                 },
-                Real::SetFilterPrimitives => Debug::SetFilterPrimitives(
-                    item.iter.cur_filter_primitives.iter().collect()
-                ),
                 Real::SetGradientStops => Debug::SetGradientStops(
                     item.iter.cur_stops.iter().collect()
                 ),
                 Real::StickyFrame(v) => Debug::StickyFrame(v),
                 Real::Rectangle(v) => Debug::Rectangle(v),
                 Real::ClearRectangle(v) => Debug::ClearRectangle(v),
                 Real::HitTest(v) => Debug::HitTest(v),
                 Real::Line(v) => Debug::Line(v),
@@ -709,20 +695,16 @@ impl<'de> Deserialize<'de> for BuiltDisp
                          filter_data.func_a_type].to_vec();
                     DisplayListBuilder::push_iter_impl(&mut temp, func_types);
                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.r_values);
                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.g_values);
                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.b_values);
                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.a_values);
                     Real::SetFilterData
                 },
-                Debug::SetFilterPrimitives(filter_primitives) => {
-                    DisplayListBuilder::push_iter_impl(&mut temp, filter_primitives);
-                    Real::SetFilterPrimitives
-                }
                 Debug::SetGradientStops(stops) => {
                     DisplayListBuilder::push_iter_impl(&mut temp, stops);
                     Real::SetGradientStops
                 },
 
                 Debug::Rectangle(v) => Real::Rectangle(v),
                 Debug::ClearRectangle(v) => Real::ClearRectangle(v),
                 Debug::HitTest(v) => Real::HitTest(v),
@@ -1438,17 +1420,16 @@ impl DisplayListBuilder {
         origin: LayoutPoint,
         spatial_id: di::SpatialId,
         is_backface_visible: bool,
         clip_id: Option<di::ClipId>,
         transform_style: di::TransformStyle,
         mix_blend_mode: di::MixBlendMode,
         filters: &[di::FilterOp],
         filter_datas: &[di::FilterData],
-        filter_primitives: &[di::FilterPrimitive],
         raster_space: di::RasterSpace,
         cache_tiles: bool,
     ) {
         if filters.len() > 0 {
             self.push_item(&di::DisplayItem::SetFilterOps);
             self.push_iter(filters);
         }
 
@@ -1459,21 +1440,16 @@ impl DisplayListBuilder {
             self.push_item(&di::DisplayItem::SetFilterData);
             self.push_iter(&func_types);
             self.push_iter(&filter_data.r_values);
             self.push_iter(&filter_data.g_values);
             self.push_iter(&filter_data.b_values);
             self.push_iter(&filter_data.a_values);
         }
 
-        if !filter_primitives.is_empty() {
-            self.push_item(&di::DisplayItem::SetFilterPrimitives);
-            self.push_iter(filter_primitives);
-        }
-
         let item = di::DisplayItem::PushStackingContext(di::PushStackingContextDisplayItem {
             origin,
             spatial_id,
             is_backface_visible,
             stacking_context: di::StackingContext {
                 transform_style,
                 mix_blend_mode,
                 clip_id,
@@ -1487,39 +1463,37 @@ impl DisplayListBuilder {
 
     /// Helper for examples/ code.
     pub fn push_simple_stacking_context(
         &mut self,
         origin: LayoutPoint,
         spatial_id: di::SpatialId,
         is_backface_visible: bool,
     ) {
-        self.push_simple_stacking_context_with_filters(origin, spatial_id, is_backface_visible, &[], &[], &[]);
+        self.push_simple_stacking_context_with_filters(origin, spatial_id, is_backface_visible, &[], &[]);
     }
 
     /// Helper for examples/ code.
     pub fn push_simple_stacking_context_with_filters(
         &mut self,
         origin: LayoutPoint,
         spatial_id: di::SpatialId,
         is_backface_visible: bool,
         filters: &[di::FilterOp],
         filter_datas: &[di::FilterData],
-        filter_primitives: &[di::FilterPrimitive],
     ) {
         self.push_stacking_context(
             origin,
             spatial_id,
             is_backface_visible,
             None,
             di::TransformStyle::Flat,
             di::MixBlendMode::Normal,
             filters,
             filter_datas,
-            filter_primitives,
             di::RasterSpace::Screen,
             /* cache_tiles = */ false,
         );
     }
 
     pub fn pop_stacking_context(&mut self) {
         self.push_item(&di::DisplayItem::PopStackingContext);
     }
rename from gfx/wr/wrench/reftests/filters/svg-filter-flood-ref.yaml
rename to gfx/wr/wrench/reftests/filters/filter-flood-ref.yaml
rename from gfx/wr/wrench/reftests/filters/svg-filter-flood.yaml
rename to gfx/wr/wrench/reftests/filters/filter-flood.yaml
--- a/gfx/wr/wrench/reftests/filters/reftest.list
+++ b/gfx/wr/wrench/reftests/filters/reftest.list
@@ -39,19 +39,9 @@ platform(linux,mac) == filter-drop-shado
 == iframe-dropshadow.yaml iframe-dropshadow-ref.yaml
 skip_on(android) == filter-mix-blend-mode.yaml filter-mix-blend-mode-ref.yaml  # Android debug: GL error 502 at blit_framebuffer (emulator) or draw_elements_instanced (Pixel2); Android opt: fails
 == fuzzy(3,20000) srgb-to-linear.yaml srgb-to-linear-ref.yaml
 != srgb-to-linear-2.yaml srgb-to-linear-ref.yaml
 != filter-blur-huge.yaml blank.yaml
 != filter-drop-shadow-huge.yaml blank.yaml
 == filter-blur-scaled.yaml filter-blur-scaled-ref.yaml
 skip_on(android) == filter-blur-scaled-xonly.yaml filter-blur-scaled-xonly.png  # fails on Android emulator and Pixel2
-skip_on(android,emulator) == svg-filter-component-transfer.yaml filter-component-transfer-ref.yaml  # fails on Android emulator
-== svg-filter-flood.yaml svg-filter-flood-ref.yaml
-skip_on(android) == svg-filter-blend.yaml svg-filter-blend-ref.yaml
-skip_on(android,device) == svg-filter-color-matrix.yaml filter-color-matrix-ref.yaml  # fails on Pixel2
-platform(linux,mac) == draw_calls(8) color_targets(8) alpha_targets(0) svg-filter-blur.yaml filter-blur.png # Extra draw call is due to render task graph workaround
-platform(linux,mac) == svg-filter-drop-shadow.yaml svg-filter-drop-shadow.png
-== fuzzy(1,10000) svg-srgb-to-linear.yaml srgb-to-linear-ref.yaml
-platform(linux,mac) == fuzzy(4,28250) svg-filter-drop-shadow-rotate.yaml svg-filter-drop-shadow-rotate-ref.yaml
-platform(linux,mac) == svg-filter-blur-transforms.yaml svg-filter-blur-transforms.png
-platform(linux,mac) == svg-filter-drop-shadow-on-viewport-edge.yaml svg-filter-drop-shadow-on-viewport-edge.png
-platform(linux,mac) == svg-filter-drop-shadow-perspective.yaml svg-filter-drop-shadow-perspective.png
+== filter-flood.yaml filter-flood-ref.yaml
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-blend-ref.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [0, 0, 50, 250]
-      items:
-        - type: rect
-          bounds: [0, 0, 50, 50]
-          color: [0, 255, 0, 1]
-        - type: rect
-          bounds: [0, 50, 50, 50]
-          color: [40, 20, 2, 1]
-        - type: rect
-          bounds: [0, 100, 50, 50]
-          color: [20, 10, 155, 1]
-        - type: rect
-          bounds: [0, 150, 50, 50]
-          color: [255, 222, 156, 1]
-        - type: rect
-          bounds: [0, 200, 50, 50]
-          color: [255, 245, 151, 1]
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-blend.yaml
+++ /dev/null
@@ -1,83 +0,0 @@
-# Tests various blend modes using the blend filter primitive.
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [0, 0, 50, 250]
-      filter-primitives:
-      - type: flood
-        color: [255, 255, 255, 1]
-        color-space: srgb
-      - type: blend
-        in1: original
-        in2: 0
-        color-space: srgb
-        blend-mode: difference
-      items:
-        - type: rect
-          bounds: [0, 0, 50, 50]
-          color: [255, 0, 255, 1]
-
-    - type: stacking-context
-      bounds: [0, 0, 50, 250]
-      filter-primitives:
-      - type: flood
-        color: [51, 51, 51, 1]
-        color-space: srgb
-      - type: blend
-        in1: original
-        in2: 0
-        color-space: srgb
-        blend-mode: multiply
-      items:
-        - type: rect
-          bounds: [0, 50, 50, 50]
-          color: [200, 100, 10, 1]
-
-    - type: stacking-context
-      bounds: [0, 0, 50, 250]
-      filter-primitives:
-      - type: flood
-        color: [255, 10, 156, 1]
-        color-space: srgb
-      - type: blend
-        in1: original
-        in2: 0
-        color-space: srgb
-        blend-mode: darken
-      items:
-        - type: rect
-          bounds: [0, 100, 50, 50]
-          color: [20, 222, 155, 1]
-
-    - type: stacking-context
-      bounds: [0, 0, 50, 250]
-      filter-primitives:
-      - type: flood
-        color: [255, 10, 156, 1]
-        color-space: srgb
-      - type: blend
-        in1: original
-        in2: 0
-        color-space: srgb
-        blend-mode: lighten
-      items:
-        - type: rect
-          bounds: [0, 150, 50, 50]
-          color: [20, 222, 155, 1]
-
-    - type: stacking-context
-      bounds: [0, 0, 50, 250]
-      filter-primitives:
-      - type: flood
-        color: [255, 10, 156, 1]
-        color-space: srgb
-      - type: blend
-        in1: original
-        in2: 0
-        color-space: srgb
-        blend-mode: exclusion
-      items:
-        - type: rect
-          bounds: [0, 200, 50, 50]
-          color: [0, 255, 24, 1]
deleted file mode 100644
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [0, 100, 300, 300]
-      transform: scale-x(0.1) rotate-z(45)
-      filter-primitives:
-      - type: blur
-        radius: 10
-        in: previous
-        color-space: srgb
-      items:
-      - type: rect
-        color: red
-        bounds: 0 0 256 256
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-blur.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [100, 100, 300, 300]
-      filter-primitives:
-      - type: blur
-        radius: 10
-        in: previous
-        color-space: srgb
-      items:
-      - image: "firefox.png"
-        bounds: 20 20 256 256
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-color-matrix.yaml
+++ /dev/null
@@ -1,54 +0,0 @@
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [0, 0, 120, 120]
-      items:
-        - type: rect
-          bounds: [0, 0, 120, 120]
-          color: [0, 0, 0, 1]
-        - type: stacking-context
-          bounds: [10, 10, 50, 50]
-          filter-primitives:
-          - type: color-matrix
-            in: previous
-            color-space: srgb
-            matrix: [0.393, 0.686, 0.534, 0,
-                     0.189, 0.168, 0.131, 0,
-                     0.349, 0.272, 0, 0,
-                     0, 0, 0, 1,
-                     0, 0, 0, 0]
-          items:
-            - type: rect
-              bounds: [0, 0, 50, 50]
-              color: [255, 0, 0, 1]
-        - type: stacking-context
-          bounds: [10, 60, 50, 50]
-          filter-primitives:
-          - type: color-matrix
-            in: previous
-            color-space: srgb
-            matrix: [-1, 0, 0, 0,
-                     0, -1, 0, 0,
-                     0, 0, -1, 0,
-                     0, 0, 0, 1,
-                     1, 1, 1, 0]
-          items:
-            - type: rect
-              bounds: [0, 0, 50, 50]
-              color: [0, 255, 0, 1]
-        - type: stacking-context
-          bounds: [60, 10, 50, 50]
-          filter-primitives:
-          - type: color-matrix
-            in: previous
-            color-space: srgb
-            matrix: [0, 0, 1, 0,
-                     0, 1, 0, 0,
-                     1, 0, 0, 0,
-                     0, 0, 0, 1,
-                     0, 0, 0, 0]
-          items:
-            - type: rect
-              bounds: [0, 0, 50, 50]
-              color: [0, 0, 255, 1]
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-component-transfer.yaml
+++ /dev/null
@@ -1,128 +0,0 @@
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [0, 0, 50, 250]
-      items:
-        - type: stacking-context
-          bounds: [0, 0, 50, 50]
-          filter-primitives:
-            - type: component-transfer
-              color-space: srgb
-              in: previous
-          filter-datas:
-            - - - Identity
-                - Identity
-                - Identity
-                - Identity
-              - []
-              - []
-              - []
-              - []
-          items:
-            - type: rect
-              bounds: [0, 0, 50, 50]
-              color: [255, 0, 255, 1]
-        - type: stacking-context
-          bounds: [0, 50, 50, 50]
-          filter-primitives:
-            - type: component-transfer
-              color-space: srgb
-              in: previous
-          filter-datas:
-            - - - Table
-                - Table
-                - Table
-                - Identity
-              - - "1"
-                - "1"
-                - "0"
-                - "0"
-              - - "0"
-                - "0"
-                - "1"
-                - "1"
-              - - "0"
-                - "1"
-                - "1"
-                - "0"
-              - []
-          items:
-            - type: rect
-              bounds: [0, 0, 50, 50]
-              color: [173, 255, 47, 1]
-        - type: stacking-context
-          bounds: [0, 100, 50, 50]
-          filter-primitives:
-            - type: component-transfer
-              color-space: srgb
-              in: previous
-          filter-datas:
-            - - - Discrete
-                - Discrete
-                - Discrete
-                - Identity
-              - - "1"
-                - "1"
-                - "0"
-                - "0"
-              - - "0"
-                - "0"
-                - "1"
-                - "1"
-              - - "0"
-                - "1"
-                - "1"
-                - "0"
-              - []
-          items:
-            - type: rect
-              bounds: [0, 0, 50, 50]
-              color: [0, 255, 255, 1]
-        - type: stacking-context
-          bounds: [0, 150, 50, 50]
-          filter-primitives:
-            - type: component-transfer
-              color-space: srgb
-              in: previous
-          filter-datas:
-            - - - Linear
-                - Linear
-                - Linear
-                - Identity
-              - - "0.5"
-                - "0.25"
-              - - "0.5"
-                - "0"
-              - - "0.5"
-                - "0.5"
-              - []
-          items:
-            - type: rect
-              bounds: [0, 0, 50, 50]
-              color: [255, 255, 0, 1]
-        - type: stacking-context
-          bounds: [0, 200, 50, 50]
-          filter-primitives:
-            - type: component-transfer
-              color-space: srgb
-              in: previous
-          filter-datas:
-            - - - Gamma
-                - Gamma
-                - Gamma
-                - Identity
-              - - "2"
-                - "5"
-                - "-1"
-              - - "2"
-                - "3"
-                - "0"
-              - - "2"
-                - "1"
-                - "-1.75"
-              - []
-          items:
-            - type: rect
-              bounds: [0, 0, 50, 50]
-              color: [135, 206, 235, 1]
deleted file mode 100644
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [10, 10, 400, 400]
-      filter-primitives:
-      - type: drop-shadow
-        offset: [10, 10]
-        radius: 20
-        color: [255, 0, 0, 1]
-        in: previous
-        color-space: srgb
-      items:
-      - type: rect
-        bounds: 0 0 256 256
-        color: green
deleted file mode 100644
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-# Tests SVG drop shadows with perspective transforms
----
-root:
-  items:
-    - type: stacking-context
-      perspective: 100
-      perspective-origin: 100 50
-      items:
-        - type: "stacking-context"
-          transform-origin: 0 250
-          transform: rotate-x(15)
-          filter-primitives:
-          - type: drop-shadow
-            color: red
-            offset: [20, 20]
-            radius: 10
-            in: previous
-            color-space: srgb
-          items:
-          - type: rect
-            color: blue
-            bounds: 0 0 200 200
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate-ref.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-# Tests SVG drop shadows with transforms
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [100, 100, 400, 400]
-      filters: drop-shadow([73, 73], 20, [255, 0, 0, 1])
-      transform: rotate-z(45)
-      items:
-      - image: "firefox.png"
-        bounds: 0 0 256 256
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-# Tests SVG drop shadows with transforms
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [100, 100, 400, 400]
-      transform: rotate-z(45)
-      filter-primitives:
-      - type: drop-shadow
-        in: previous
-        offset: [73, 73]
-        radius: 20
-        color: [255, 0, 0, 1]
-        color-space: srgb
-      items:
-      - image: "firefox.png"
-        bounds: 0 0 256 256
deleted file mode 100644
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-# Tests that SVG drop shadows are working properly
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [100, 100, 400, 400]
-      filter-primitives:
-      - type: drop-shadow
-        in: previous
-        offset: [73, 73]
-        radius: 20
-        color: [255, 0, 0, 1]
-        color-space: srgb
-      items:
-      - image: "firefox.png"
-        bounds: 0 0 256 256
deleted file mode 100644
--- a/gfx/wr/wrench/reftests/filters/svg-srgb-to-linear.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-# this test ensures that a sRGB -> linear-RGB -> sRGB results in no change (with exception to rounding error)
----
-root:
-  items:
-    - type: stacking-context
-      bounds: [0, 0, 300, 100]
-      filter-primitives:
-      - type: identity
-        in: previous
-        color-space: linear-rgb
-      items:
-        - type: rect
-          bounds: [100, 0, 100, 100]
-          color: [200, 200, 200, 1.0]
-        - type: rect
-          bounds: [100, 0, 100, 100]
-          color: [100, 100, 100, 1.0]
-        - type: rect
-          bounds: [200, 0, 100, 100]
-          color: [50, 50, 50, 1.0]
--- a/gfx/wr/wrench/reftests/mask/reftest.list
+++ b/gfx/wr/wrench/reftests/mask/reftest.list
@@ -5,12 +5,12 @@ skip_on(android,emulator) == nested-mask
 != mask.yaml green.yaml
 == aligned-layer-rect.yaml aligned-layer-rect-ref.yaml
 == mask-transformed-to-empty-rect.yaml mask-transformed-to-empty-rect-ref.yaml
 platform(linux,mac) == rounded-corners.yaml rounded-corners.png
 != mask.yaml out-of-bounds.yaml
 platform(linux,mac) fuzzy(1,17500) color_targets(3) alpha_targets(1) == mask-atomicity.yaml mask-atomicity-ref.yaml
 platform(linux,mac) fuzzy(1,17500) == mask-atomicity-tiling.yaml mask-atomicity-ref.yaml
 platform(linux,mac) == mask-perspective.yaml mask-perspective.png
-skip_on(android,emulator) == fuzzy(1,7) mask-perspective-tiling.yaml mask-perspective.yaml  # Android emulator: GL error 502 at tex_sub_image_3d_pbo, fails on opt
+skip_on(android,emulator) == fuzzy(1,6) mask-perspective-tiling.yaml mask-perspective.yaml  # Android emulator: GL error 502 at tex_sub_image_3d_pbo, fails on opt
 platform(linux,mac) == checkerboard.yaml checkerboard.png
 skip_on(android) == checkerboard.yaml checkerboard-tiling.yaml  # Android emulator: GL error 502 at blit_framebuffer, fails on opt emulator and on a Pixel2
 == missing-mask.yaml missing-mask-ref.yaml
--- a/gfx/wr/wrench/src/yaml_frame_reader.rs
+++ b/gfx/wr/wrench/src/yaml_frame_reader.rs
@@ -1876,28 +1876,26 @@ impl YamlFrameReader {
             if let Some(size) = yaml["scroll-offset"].as_point() {
                 let external_id = ExternalScrollId(0, dl.pipeline_id);
                 self.scroll_offsets.insert(external_id, LayoutPoint::new(size.x, size.y));
             }
         }
 
         let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]);
         let filter_datas = yaml["filter-datas"].as_vec_filter_data().unwrap_or(vec![]);
-        let filter_primitives = yaml["filter-primitives"].as_vec_filter_primitive().unwrap_or(vec![]);
 
         dl.push_stacking_context(
             bounds.origin,
             *self.spatial_id_stack.last().unwrap(),
             info.is_backface_visible,
             clip_node_id,
             transform_style,
             mix_blend_mode,
             &filters,
             &filter_datas,
-            &filter_primitives,
             raster_space,
             cache_tiles,
         );
 
         if !yaml["items"].is_badvalue() {
             self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
         }
 
--- a/gfx/wr/wrench/src/yaml_frame_writer.rs
+++ b/gfx/wr/wrench/src/yaml_frame_writer.rs
@@ -67,24 +67,16 @@ fn color_to_string(value: ColorF) -> Str
             value.r * 255.0,
             value.g * 255.0,
             value.b * 255.0,
             value.a
         )
     }
 }
 
-fn filter_input_to_string(input: FilterPrimitiveInput) -> String {
-    match input {
-        FilterPrimitiveInput::Original => "original".into(),
-        FilterPrimitiveInput::Previous => "previous".into(),
-        FilterPrimitiveInput::OutputOfPrimitiveIndex(index) => index.to_string(),
-    }
-}
-
 fn color_node(parent: &mut Table, key: &str, value: ColorF) {
     yaml_node(parent, key, Yaml::String(color_to_string(value)));
 }
 
 fn point_node<U>(parent: &mut Table, key: &str, value: &TypedPoint2D<f32, U>) {
     f32_vec_node(parent, key, &[value.x, value.y]);
 }
 
@@ -135,20 +127,16 @@ fn f32_node(parent: &mut Table, key: &st
 fn bool_node(parent: &mut Table, key: &str, value: bool) {
     yaml_node(parent, key, Yaml::Boolean(value));
 }
 
 fn table_node(parent: &mut Table, key: &str, value: Table) {
     yaml_node(parent, key, Yaml::Hash(value));
 }
 
-fn filter_input_node(parent: &mut Table, key: &str, value: FilterPrimitiveInput) {
-    yaml_node(parent, key, Yaml::String(filter_input_to_string(value)));
-}
-
 fn string_vec_yaml(value: &[String], check_unique: bool) -> Yaml {
     if !value.is_empty() && check_unique && array_elements_are_same(value) {
         Yaml::String(value[0].clone())
     } else {
         Yaml::Array(value.iter().map(|v| Yaml::String(v.clone())).collect())
     }
 }
 
@@ -260,17 +248,16 @@ fn shadow_parameters(shadow: &Shadow) ->
 }
 
 fn write_stacking_context(
     parent: &mut Table,
     sc: &StackingContext,
     properties: &SceneProperties,
     filter_iter: impl IntoIterator<Item = FilterOp>,
     filter_data_iter: &[TempFilterData],
-    filter_primitive_iter: impl IntoIterator<Item = FilterPrimitive>,
 ) {
     enum_node(parent, "transform-style", sc.transform_style);
 
     let raster_space = match sc.raster_space {
         RasterSpace::Local(scale) => {
             format!("local({})", scale)
         }
         RasterSpace::Screen => {
@@ -357,68 +344,16 @@ fn write_stacking_context(
             Yaml::Array(g_values),
             Yaml::Array(b_values),
             Yaml::Array(a_values),
         ].to_vec();
         filter_datas.push(Yaml::Array(avec));
     }
 
     yaml_node(parent, "filter-datas", Yaml::Array(filter_datas));
-
-    // filter primitives
-    let mut filter_primitives = vec![];
-    for filter_primitive in filter_primitive_iter {
-        let mut table = new_table();
-        match filter_primitive.kind {
-            FilterPrimitiveKind::Identity(identity_primitive) => {
-                yaml_node(&mut table, "type", Yaml::String("identity".into()));
-                filter_input_node(&mut table, "in", identity_primitive.input);
-            }
-            FilterPrimitiveKind::Blend(blend_primitive) => {
-                yaml_node(&mut table, "type", Yaml::String("blend".into()));
-                filter_input_node(&mut table, "in1", blend_primitive.input1);
-                filter_input_node(&mut table, "in2", blend_primitive.input2);
-                enum_node(&mut table, "mode", blend_primitive.mode);
-            }
-            FilterPrimitiveKind::Flood(flood_primitive) => {
-                yaml_node(&mut table, "type", Yaml::String("flood".into()));
-                color_node(&mut table, "color", flood_primitive.color);
-            }
-            FilterPrimitiveKind::Blur(blur_primitive) => {
-                yaml_node(&mut table, "type", Yaml::String("blur".into()));
-                filter_input_node(&mut table, "in", blur_primitive.input);
-                f32_node(&mut table, "radius", blur_primitive.radius);
-            }
-            FilterPrimitiveKind::Opacity(opacity_primitive) => {
-                yaml_node(&mut table, "type", Yaml::String("opacity".into()));
-                filter_input_node(&mut table, "in", opacity_primitive.input);
-                f32_node(&mut table, "opacity", opacity_primitive.opacity);
-            }
-            FilterPrimitiveKind::ColorMatrix(color_matrix_primitive) => {
-                yaml_node(&mut table, "type", Yaml::String("color-matrix".into()));
-                filter_input_node(&mut table, "in", color_matrix_primitive.input);
-                f32_vec_node(&mut table, "matrix", &color_matrix_primitive.matrix);
-            }
-            FilterPrimitiveKind::DropShadow(drop_shadow_primitive) => {
-                yaml_node(&mut table, "type", Yaml::String("drop-shadow".into()));
-                filter_input_node(&mut table, "in", drop_shadow_primitive.input);
-                vector_node(&mut table, "offset", &drop_shadow_primitive.shadow.offset);
-                color_node(&mut table, "color", drop_shadow_primitive.shadow.color);
-                f32_node(&mut table, "radius", drop_shadow_primitive.shadow.blur_radius);
-            }
-            FilterPrimitiveKind::ComponentTransfer(component_transfer_primitive) => {
-                yaml_node(&mut table, "type", Yaml::String("component-transfer".into()));
-                filter_input_node(&mut table, "in", component_transfer_primitive.input);
-            }
-        }
-        enum_node(&mut table, "color-space", filter_primitive.color_space);
-        filter_primitives.push(Yaml::Hash(table));
-    }
-
-    yaml_node(parent, "filter-primitives", Yaml::Array(filter_primitives));
 }
 
 #[cfg(target_os = "macos")]
 fn native_font_handle_to_yaml(
     rsrc: &mut ResourceGenerator,
     handle: &NativeFontHandle,
     parent: &mut yaml_rust::yaml::Hash,
     path_opt: &mut Option<PathBuf>,
@@ -1225,17 +1160,16 @@ impl YamlFrameWriter {
                     point_node(&mut v, "origin", &item.origin);
                     bool_node(&mut v, "backface-visible", item.is_backface_visible);
                     write_stacking_context(
                         &mut v,
                         &item.stacking_context,
                         &scene.properties,
                         base.filters(),
                         base.filter_datas(),
-                        base.filter_primitives(),
                     );
 
                     let mut sub_iter = base.sub_iter();
                     self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
                     continue_traversal = Some(sub_iter);
                 }
                 DisplayItem::PushReferenceFrame(item) => {
                     str_node(&mut v, "type", "reference-frame");
@@ -1338,21 +1272,19 @@ impl YamlFrameWriter {
                         Yaml::Real(item.previously_applied_offset.y.to_string()),
                     ];
                     yaml_node(&mut v, "previously-applied-offset", Yaml::Array(applied));
                 }
 
                 DisplayItem::PopReferenceFrame |
                 DisplayItem::PopStackingContext => return,
 
-                DisplayItem::SetGradientStops |
-                DisplayItem::SetFilterOps |
-                DisplayItem::SetFilterData |
-                DisplayItem::SetFilterPrimitives => panic!("dummy item yielded?"),
-
+                DisplayItem::SetGradientStops => panic!("dummy item yielded?"),
+                DisplayItem::SetFilterOps => panic!("dummy item yielded?"),
+                DisplayItem::SetFilterData => panic!("dummy item yielded?"),
                 DisplayItem::PushShadow(item) => {
                     str_node(&mut v, "type", "shadow");
                     vector_node(&mut v, "offset", &item.shadow.offset);
                     color_node(&mut v, "color", item.shadow.color);
                     f32_node(&mut v, "blur-radius", item.shadow.blur_radius);
                 }
                 DisplayItem::PopAllShadows => {
                     str_node(&mut v, "type", "pop-all-shadows");
--- a/gfx/wr/wrench/src/yaml_helper.rs
+++ b/gfx/wr/wrench/src/yaml_helper.rs
@@ -33,20 +33,16 @@ pub trait YamlHelper {
     fn as_transform_style(&self) -> Option<TransformStyle>;
     fn as_raster_space(&self) -> Option<RasterSpace>;
     fn as_clip_mode(&self) -> Option<ClipMode>;
     fn as_mix_blend_mode(&self) -> Option<MixBlendMode>;
     fn as_filter_op(&self) -> Option<FilterOp>;
     fn as_vec_filter_op(&self) -> Option<Vec<FilterOp>>;
     fn as_filter_data(&self) -> Option<FilterData>;
     fn as_vec_filter_data(&self) -> Option<Vec<FilterData>>;
-    fn as_filter_input(&self) -> Option<FilterPrimitiveInput>;
-    fn as_filter_primitive(&self) -> Option<FilterPrimitive>;
-    fn as_vec_filter_primitive(&self) -> Option<Vec<FilterPrimitive>>;
-    fn as_color_space(&self) -> Option<ColorSpace>;
 }
 
 fn string_to_color(color: &str) -> Option<ColorF> {
     match color {
         "red" => Some(ColorF::new(1.0, 0.0, 0.0, 1.0)),
         "green" => Some(ColorF::new(0.0, 1.0, 0.0, 1.0)),
         "blue" => Some(ColorF::new(0.0, 0.0, 1.0, 1.0)),
         "white" => Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
@@ -151,24 +147,16 @@ define_string_enum!(
         Identity = "Identity",
         Table = "Table",
         Discrete = "Discrete",
         Linear = "Linear",
         Gamma = "Gamma"
     ]
 );
 
-define_string_enum!(
-    ColorSpace,
-    [
-        Srgb = "srgb",
-        LinearRgb = "linear-rgb"
-    ]
-);
-
 // Rotate around `axis` by `degrees` angle
 fn make_rotation(
     origin: &LayoutPoint,
     degrees: f32,
     axis_x: f32,
     axis_y: f32,
     axis_z: f32,
 ) -> LayoutTransform {
@@ -681,115 +669,16 @@ impl YamlHelper for Yaml {
                         }
                     }
                 }
             }
         }
         None
     }
 
-    fn as_filter_input(&self) -> Option<FilterPrimitiveInput> {
-        if let Some(input) = self.as_str() {
-            match input {
-                "original" => Some(FilterPrimitiveInput::Original),
-                "previous" => Some(FilterPrimitiveInput::Previous),
-                _ => None,
-            }
-        } else if let Some(index) = self.as_i64() {
-            if index >= 0 {
-                Some(FilterPrimitiveInput::OutputOfPrimitiveIndex(index as usize))
-            } else {
-                panic!("Filter input index cannot be negative");
-            }
-        } else {
-            panic!("Invalid filter input");
-        }
-    }
-
     fn as_vec_filter_data(&self) -> Option<Vec<FilterData>> {
         if let Some(v) = self.as_vec() {
             Some(v.iter().map(|x| x.as_filter_data().unwrap()).collect())
         } else {
             self.as_filter_data().map(|data| vec![data])
         }
     }
-
-    fn as_filter_primitive(&self) -> Option<FilterPrimitive> {
-        if let Some(filter_type) = self["type"].as_str() {
-            let kind = match filter_type {
-                "identity" => {
-                    FilterPrimitiveKind::Identity(IdentityPrimitive {
-                        input: self["in"].as_filter_input().unwrap(),
-                    })
-                }
-                "blend" => {
-                    FilterPrimitiveKind::Blend(BlendPrimitive {
-                        input1: self["in1"].as_filter_input().unwrap(),
-                        input2: self["in2"].as_filter_input().unwrap(),
-                        mode: self["blend-mode"].as_mix_blend_mode().unwrap(),
-                    })
-                }
-                "flood" => {
-                    FilterPrimitiveKind::Flood(FloodPrimitive {
-                        color: self["color"].as_colorf().unwrap(),
-                    })
-                }
-                "blur" => {
-                    FilterPrimitiveKind::Blur(BlurPrimitive {
-                        input: self["in"].as_filter_input().unwrap(),
-                        radius: self["radius"].as_f32().unwrap(),
-                    })
-                }
-                "opacity" => {
-                    FilterPrimitiveKind::Opacity(OpacityPrimitive {
-                        input: self["in"].as_filter_input().unwrap(),
-                        opacity: self["opacity"].as_f32().unwrap(),
-                    })
-                }
-                "color-matrix" => {
-                    let m: Vec<f32> = self["matrix"].as_vec_f32().unwrap();
-                    let mut matrix: [f32; 20] = [0.0; 20];
-                    matrix.clone_from_slice(&m);
-
-                    FilterPrimitiveKind::ColorMatrix(ColorMatrixPrimitive {
-                        input: self["in"].as_filter_input().unwrap(),
-                        matrix,
-                    })
-                }
-                "drop-shadow" => {
-                    FilterPrimitiveKind::DropShadow(DropShadowPrimitive {
-                        input: self["in"].as_filter_input().unwrap(),
-                        shadow: Shadow {
-                            offset: self["offset"].as_vector().unwrap(),
-                            color: self["color"].as_colorf().unwrap(),
-                            blur_radius: self["radius"].as_f32().unwrap(),
-                        }
-                    })
-                }
-                "component-transfer" => {
-                    FilterPrimitiveKind::ComponentTransfer(ComponentTransferPrimitive {
-                        input: self["in"].as_filter_input().unwrap(),
-                    })
-                }
-                _ => return None,
-            };
-
-            Some(FilterPrimitive {
-                kind,
-                color_space: self["color-space"].as_color_space().unwrap_or(ColorSpace::LinearRgb),
-            })
-        } else {
-            None
-        }
-    }
-
-    fn as_vec_filter_primitive(&self) -> Option<Vec<FilterPrimitive>> {
-        if let Some(v) = self.as_vec() {
-            Some(v.iter().map(|x| x.as_filter_primitive().unwrap()).collect())
-        } else {
-            self.as_filter_primitive().map(|data| vec![data])
-        }
-    }
-
-    fn as_color_space(&self) -> Option<ColorSpace> {
-        self.as_str().and_then(|x| StringEnum::from_str(x))
-    }
 }