[Impeller] Gaussian blur: Add alpha mask specialization (#40707)

diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index e890eab..b08e3e2 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1246,10 +1246,12 @@
 ORIGIN: ../../../flutter/impeller/entity/shaders/color_matrix_color_filter.vert + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/entity/shaders/conical_gradient_fill.frag + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/entity/shaders/conical_gradient_ssbo_fill.frag + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur.frag + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur.glsl + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur.vert + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur_decal.frag + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur.vert + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_decal.frag + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_nodecal.frag + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_decal.frag + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_nodecal.frag + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas_sdf.frag + ../../../flutter/LICENSE
@@ -3810,10 +3812,12 @@
 FILE: ../../../flutter/impeller/entity/shaders/color_matrix_color_filter.vert
 FILE: ../../../flutter/impeller/entity/shaders/conical_gradient_fill.frag
 FILE: ../../../flutter/impeller/entity/shaders/conical_gradient_ssbo_fill.frag
-FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur.frag
-FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur.glsl
-FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur.vert
-FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur_decal.frag
+FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl
+FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur.vert
+FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_decal.frag
+FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_nodecal.frag
+FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_decal.frag
+FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_nodecal.frag
 FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag
 FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert
 FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas_sdf.frag
diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn
index 9689ac9..69c7726 100644
--- a/impeller/entity/BUILD.gn
+++ b/impeller/entity/BUILD.gn
@@ -35,9 +35,11 @@
     "shaders/color_matrix_color_filter.frag",
     "shaders/color_matrix_color_filter.vert",
     "shaders/conical_gradient_fill.frag",
-    "shaders/gaussian_blur.frag",
-    "shaders/gaussian_blur_decal.frag",
-    "shaders/gaussian_blur.vert",
+    "shaders/gaussian_blur/gaussian_blur.vert",
+    "shaders/gaussian_blur/gaussian_blur_alpha_decal.frag",
+    "shaders/gaussian_blur/gaussian_blur_alpha_nodecal.frag",
+    "shaders/gaussian_blur/gaussian_blur_noalpha_decal.frag",
+    "shaders/gaussian_blur/gaussian_blur_noalpha_nodecal.frag",
     "shaders/glyph_atlas.frag",
     "shaders/glyph_atlas.vert",
     "shaders/glyph_atlas_sdf.frag",
diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc
index 3c2545c..9b421ed 100644
--- a/impeller/entity/contents/content_context.cc
+++ b/impeller/entity/contents/content_context.cc
@@ -261,10 +261,14 @@
       CreateDefaultPipeline<PositionUVPipeline>(*context_);
   tiled_texture_pipelines_[{}] =
       CreateDefaultPipeline<TiledTexturePipeline>(*context_);
-  gaussian_blur_pipelines_[{}] =
-      CreateDefaultPipeline<GaussianBlurPipeline>(*context_);
-  gaussian_blur_decal_pipelines_[{}] =
+  gaussian_blur_alpha_decal_pipelines_[{}] =
+      CreateDefaultPipeline<GaussianBlurAlphaDecalPipeline>(*context_);
+  gaussian_blur_alpha_nodecal_pipelines_[{}] =
+      CreateDefaultPipeline<GaussianBlurAlphaPipeline>(*context_);
+  gaussian_blur_noalpha_decal_pipelines_[{}] =
       CreateDefaultPipeline<GaussianBlurDecalPipeline>(*context_);
+  gaussian_blur_noalpha_nodecal_pipelines_[{}] =
+      CreateDefaultPipeline<GaussianBlurPipeline>(*context_);
   border_mask_blur_pipelines_[{}] =
       CreateDefaultPipeline<BorderMaskBlurPipeline>(*context_);
   morphology_filter_pipelines_[{}] =
diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h
index f9ab7ac..f139293 100644
--- a/impeller/entity/contents/content_context.h
+++ b/impeller/entity/contents/content_context.h
@@ -12,6 +12,12 @@
 #include "flutter/fml/logging.h"
 #include "flutter/fml/macros.h"
 #include "impeller/base/validation.h"
+#include "impeller/entity/entity.h"
+#include "impeller/renderer/capabilities.h"
+#include "impeller/renderer/formats.h"
+#include "impeller/renderer/pipeline.h"
+#include "impeller/scene/scene_context.h"
+
 #include "impeller/entity/blend.frag.h"
 #include "impeller/entity/blend.vert.h"
 #include "impeller/entity/border_mask_blur.frag.h"
@@ -19,10 +25,6 @@
 #include "impeller/entity/color_matrix_color_filter.frag.h"
 #include "impeller/entity/color_matrix_color_filter.vert.h"
 #include "impeller/entity/conical_gradient_fill.frag.h"
-#include "impeller/entity/entity.h"
-#include "impeller/entity/gaussian_blur.frag.h"
-#include "impeller/entity/gaussian_blur.vert.h"
-#include "impeller/entity/gaussian_blur_decal.frag.h"
 #include "impeller/entity/glyph_atlas.frag.h"
 #include "impeller/entity/glyph_atlas.vert.h"
 #include "impeller/entity/glyph_atlas_sdf.frag.h"
@@ -48,10 +50,12 @@
 #include "impeller/entity/vertices.frag.h"
 #include "impeller/entity/yuv_to_rgb_filter.frag.h"
 #include "impeller/entity/yuv_to_rgb_filter.vert.h"
-#include "impeller/renderer/capabilities.h"
-#include "impeller/renderer/formats.h"
-#include "impeller/renderer/pipeline.h"
-#include "impeller/scene/scene_context.h"
+
+#include "impeller/entity/gaussian_blur.vert.h"
+#include "impeller/entity/gaussian_blur_alpha_decal.frag.h"
+#include "impeller/entity/gaussian_blur_alpha_nodecal.frag.h"
+#include "impeller/entity/gaussian_blur_noalpha_decal.frag.h"
+#include "impeller/entity/gaussian_blur_noalpha_nodecal.frag.h"
 
 #include "impeller/entity/position_color.vert.h"
 
@@ -132,10 +136,18 @@
     RenderPipelineT<TextureFillVertexShader, TiledTextureFillFragmentShader>;
 using TiledTexturePipeline = RenderPipelineT<TiledTextureFillVertexShader,
                                              TiledTextureFillFragmentShader>;
-using GaussianBlurPipeline =
-    RenderPipelineT<GaussianBlurVertexShader, GaussianBlurFragmentShader>;
+using GaussianBlurAlphaDecalPipeline =
+    RenderPipelineT<GaussianBlurVertexShader,
+                    GaussianBlurAlphaDecalFragmentShader>;
+using GaussianBlurAlphaPipeline =
+    RenderPipelineT<GaussianBlurVertexShader,
+                    GaussianBlurAlphaNodecalFragmentShader>;
 using GaussianBlurDecalPipeline =
-    RenderPipelineT<GaussianBlurVertexShader, GaussianBlurDecalFragmentShader>;
+    RenderPipelineT<GaussianBlurVertexShader,
+                    GaussianBlurNoalphaDecalFragmentShader>;
+using GaussianBlurPipeline =
+    RenderPipelineT<GaussianBlurVertexShader,
+                    GaussianBlurNoalphaNodecalFragmentShader>;
 using BorderMaskBlurPipeline =
     RenderPipelineT<BorderMaskBlurVertexShader, BorderMaskBlurFragmentShader>;
 using MorphologyFilterPipeline =
@@ -388,14 +400,24 @@
     return GetPipeline(tiled_texture_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetGaussianBlurPipeline(
+  std::shared_ptr<Pipeline<PipelineDescriptor>>
+  GetGaussianBlurAlphaDecalPipeline(ContentContextOptions opts) const {
+    return GetPipeline(gaussian_blur_alpha_decal_pipelines_, opts);
+  }
+
+  std::shared_ptr<Pipeline<PipelineDescriptor>> GetGaussianBlurAlphaPipeline(
       ContentContextOptions opts) const {
-    return GetPipeline(gaussian_blur_pipelines_, opts);
+    return GetPipeline(gaussian_blur_alpha_nodecal_pipelines_, opts);
   }
 
   std::shared_ptr<Pipeline<PipelineDescriptor>> GetGaussianBlurDecalPipeline(
       ContentContextOptions opts) const {
-    return GetPipeline(gaussian_blur_decal_pipelines_, opts);
+    return GetPipeline(gaussian_blur_noalpha_decal_pipelines_, opts);
+  }
+
+  std::shared_ptr<Pipeline<PipelineDescriptor>> GetGaussianBlurPipeline(
+      ContentContextOptions opts) const {
+    return GetPipeline(gaussian_blur_noalpha_nodecal_pipelines_, opts);
   }
 
   std::shared_ptr<Pipeline<PipelineDescriptor>> GetBorderMaskBlurPipeline(
@@ -665,8 +687,14 @@
   mutable Variants<TexturePipeline> texture_pipelines_;
   mutable Variants<PositionUVPipeline> position_uv_pipelines_;
   mutable Variants<TiledTexturePipeline> tiled_texture_pipelines_;
-  mutable Variants<GaussianBlurPipeline> gaussian_blur_pipelines_;
-  mutable Variants<GaussianBlurDecalPipeline> gaussian_blur_decal_pipelines_;
+  mutable Variants<GaussianBlurAlphaDecalPipeline>
+      gaussian_blur_alpha_decal_pipelines_;
+  mutable Variants<GaussianBlurAlphaPipeline>
+      gaussian_blur_alpha_nodecal_pipelines_;
+  mutable Variants<GaussianBlurDecalPipeline>
+      gaussian_blur_noalpha_decal_pipelines_;
+  mutable Variants<GaussianBlurPipeline>
+      gaussian_blur_noalpha_nodecal_pipelines_;
   mutable Variants<BorderMaskBlurPipeline> border_mask_blur_pipelines_;
   mutable Variants<MorphologyFilterPipeline> morphology_filter_pipelines_;
   mutable Variants<ColorMatrixColorFilterPipeline>
diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
index 6683a71..deec204 100644
--- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
+++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
@@ -87,8 +87,8 @@
     const Entity& entity,
     const Matrix& effect_transform,
     const Rect& coverage) const {
-  using VS = GaussianBlurPipeline::VertexShader;
-  using FS = GaussianBlurPipeline::FragmentShader;
+  using VS = GaussianBlurAlphaDecalPipeline::VertexShader;
+  using FS = GaussianBlurAlphaDecalPipeline::FragmentShader;
 
   //----------------------------------------------------------------------------
   /// Handle inputs.
@@ -192,7 +192,7 @@
     frame_info.alpha_mask_sampler_y_coord_scale =
         source_snapshot->texture->GetYCoordScale();
 
-    FS::FragInfo frag_info;
+    FS::BlurInfo frag_info;
     auto r = Radius{transformed_blur_radius_length};
     frag_info.blur_sigma = Sigma{r}.sigma;
     frag_info.blur_radius = r.radius;
@@ -201,9 +201,6 @@
     frag_info.blur_direction =
         pass_transform.Invert().TransformDirection(Vector2(1, 0)).Normalize();
 
-    frag_info.src_factor = src_color_factor_;
-    frag_info.inner_blur_factor = inner_blur_factor_;
-    frag_info.outer_blur_factor = outer_blur_factor_;
     frag_info.texture_size = Point(input_snapshot->GetCoverage().value().size);
 
     Command cmd;
@@ -217,10 +214,8 @@
     auto source_descriptor = source_snapshot->sampler_descriptor;
     switch (tile_mode_) {
       case Entity::TileMode::kDecal:
-        cmd.pipeline = renderer.GetGaussianBlurDecalPipeline(options);
         break;
       case Entity::TileMode::kClamp:
-        cmd.pipeline = renderer.GetGaussianBlurPipeline(options);
         input_descriptor.width_address_mode = SamplerAddressMode::kClampToEdge;
         input_descriptor.height_address_mode = SamplerAddressMode::kClampToEdge;
         source_descriptor.width_address_mode = SamplerAddressMode::kClampToEdge;
@@ -228,14 +223,12 @@
             SamplerAddressMode::kClampToEdge;
         break;
       case Entity::TileMode::kMirror:
-        cmd.pipeline = renderer.GetGaussianBlurPipeline(options);
         input_descriptor.width_address_mode = SamplerAddressMode::kMirror;
         input_descriptor.height_address_mode = SamplerAddressMode::kMirror;
         source_descriptor.width_address_mode = SamplerAddressMode::kMirror;
         source_descriptor.height_address_mode = SamplerAddressMode::kMirror;
         break;
       case Entity::TileMode::kRepeat:
-        cmd.pipeline = renderer.GetGaussianBlurPipeline(options);
         input_descriptor.width_address_mode = SamplerAddressMode::kRepeat;
         input_descriptor.height_address_mode = SamplerAddressMode::kRepeat;
         source_descriptor.width_address_mode = SamplerAddressMode::kRepeat;
@@ -243,16 +236,38 @@
         break;
     }
 
+    bool has_alpha_mask = blur_style_ != BlurStyle::kNormal;
+    bool has_decal_specialization = tile_mode_ == Entity::TileMode::kDecal;
+
+    if (has_alpha_mask && has_decal_specialization) {
+      cmd.pipeline = renderer.GetGaussianBlurAlphaDecalPipeline(options);
+    } else if (has_alpha_mask) {
+      cmd.pipeline = renderer.GetGaussianBlurAlphaPipeline(options);
+    } else if (has_decal_specialization) {
+      cmd.pipeline = renderer.GetGaussianBlurDecalPipeline(options);
+    } else {
+      cmd.pipeline = renderer.GetGaussianBlurPipeline(options);
+    }
+
     FS::BindTextureSampler(
         cmd, input_snapshot->texture,
         renderer.GetContext()->GetSamplerLibrary()->GetSampler(
             input_descriptor));
-    FS::BindAlphaMaskSampler(
-        cmd, source_snapshot->texture,
-        renderer.GetContext()->GetSamplerLibrary()->GetSampler(
-            source_descriptor));
     VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
-    FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
+    FS::BindBlurInfo(cmd, host_buffer.EmplaceUniform(frag_info));
+
+    if (has_alpha_mask) {
+      FS::MaskInfo mask_info;
+      mask_info.src_factor = src_color_factor_;
+      mask_info.inner_blur_factor = inner_blur_factor_;
+      mask_info.outer_blur_factor = outer_blur_factor_;
+
+      FS::BindAlphaMaskSampler(
+          cmd, source_snapshot->texture,
+          renderer.GetContext()->GetSamplerLibrary()->GetSampler(
+              source_descriptor));
+      FS::BindMaskInfo(cmd, host_buffer.EmplaceUniform(mask_info));
+    }
 
     return pass.AddCommand(cmd);
   };
diff --git a/impeller/entity/shaders/gaussian_blur.glsl b/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl
similarity index 73%
rename from impeller/entity/shaders/gaussian_blur.glsl
rename to impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl
index 718b482..4a21830 100644
--- a/impeller/entity/shaders/gaussian_blur.glsl
+++ b/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl
@@ -19,9 +19,8 @@
 #include <impeller/types.glsl>
 
 uniform sampler2D texture_sampler;
-uniform sampler2D alpha_mask_sampler;
 
-uniform FragInfo {
+uniform BlurInfo {
   vec2 texture_size;
   vec2 blur_direction;
 
@@ -31,12 +30,27 @@
   // radius is used to limit how much of the function is integrated.
   float blur_sigma;
   float blur_radius;
+}
+blur_info;
 
+#if ENABLE_ALPHA_MASK
+uniform sampler2D alpha_mask_sampler;
+
+uniform MaskInfo {
   float src_factor;
   float inner_blur_factor;
   float outer_blur_factor;
 }
-frag_info;
+mask_info;
+#endif
+
+vec4 Sample(sampler2D tex, vec2 coords) {
+#if ENABLE_DECAL_SPECIALIZATION
+  return IPSampleDecal(tex, coords);
+#else
+  return texture(tex, coords);
+#endif
+}
 
 in vec2 v_texture_coords;
 in vec2 v_src_texture_coords;
@@ -46,10 +60,10 @@
 void main() {
   vec4 total_color = vec4(0);
   float gaussian_integral = 0;
-  vec2 blur_uv_offset = frag_info.blur_direction / frag_info.texture_size;
+  vec2 blur_uv_offset = blur_info.blur_direction / blur_info.texture_size;
 
-  for (float i = -frag_info.blur_radius; i <= frag_info.blur_radius; i++) {
-    float gaussian = IPGaussian(i, frag_info.blur_sigma);
+  for (float i = -blur_info.blur_radius; i <= blur_info.blur_radius; i++) {
+    float gaussian = IPGaussian(i, blur_info.blur_sigma);
     gaussian_integral += gaussian;
     total_color +=
         gaussian *
@@ -58,13 +72,15 @@
         );
   }
 
-  vec4 blur_color = total_color / gaussian_integral;
+  frag_color = total_color / gaussian_integral;
 
+#if ENABLE_ALPHA_MASK
   vec4 src_color = Sample(alpha_mask_sampler,   // sampler
                           v_src_texture_coords  // texture coordinates
   );
-  float blur_factor = frag_info.inner_blur_factor * float(src_color.a > 0) +
-                      frag_info.outer_blur_factor * float(src_color.a == 0);
+  float blur_factor = mask_info.inner_blur_factor * float(src_color.a > 0) +
+                      mask_info.outer_blur_factor * float(src_color.a == 0);
 
-  frag_color = blur_color * blur_factor + src_color * frag_info.src_factor;
+  frag_color = frag_color * blur_factor + src_color * mask_info.src_factor;
+#endif
 }
diff --git a/impeller/entity/shaders/gaussian_blur.vert b/impeller/entity/shaders/gaussian_blur/gaussian_blur.vert
similarity index 100%
rename from impeller/entity/shaders/gaussian_blur.vert
rename to impeller/entity/shaders/gaussian_blur/gaussian_blur.vert
diff --git a/impeller/entity/shaders/gaussian_blur.frag b/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_decal.frag
similarity index 63%
copy from impeller/entity/shaders/gaussian_blur.frag
copy to impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_decal.frag
index 8b483ae..5c60a89 100644
--- a/impeller/entity/shaders/gaussian_blur.frag
+++ b/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_decal.frag
@@ -2,10 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <impeller/texture.glsl>
-
-vec4 Sample(sampler2D tex, vec2 coords) {
-  return texture(tex, coords);
-}
+#define ENABLE_ALPHA_MASK 1
+#define ENABLE_DECAL_SPECIALIZATION 1
 
 #include "gaussian_blur.glsl"
diff --git a/impeller/entity/shaders/gaussian_blur.frag b/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_nodecal.frag
similarity index 63%
rename from impeller/entity/shaders/gaussian_blur.frag
rename to impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_nodecal.frag
index 8b483ae..90b21c1 100644
--- a/impeller/entity/shaders/gaussian_blur.frag
+++ b/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_nodecal.frag
@@ -2,10 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <impeller/texture.glsl>
-
-vec4 Sample(sampler2D tex, vec2 coords) {
-  return texture(tex, coords);
-}
+#define ENABLE_ALPHA_MASK 1
+#define ENABLE_DECAL_SPECIALIZATION 0
 
 #include "gaussian_blur.glsl"
diff --git a/impeller/entity/shaders/gaussian_blur.frag b/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_decal.frag
similarity index 63%
copy from impeller/entity/shaders/gaussian_blur.frag
copy to impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_decal.frag
index 8b483ae..57ae5a8 100644
--- a/impeller/entity/shaders/gaussian_blur.frag
+++ b/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_decal.frag
@@ -2,10 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <impeller/texture.glsl>
-
-vec4 Sample(sampler2D tex, vec2 coords) {
-  return texture(tex, coords);
-}
+#define ENABLE_ALPHA_MASK 0
+#define ENABLE_DECAL_SPECIALIZATION 1
 
 #include "gaussian_blur.glsl"
diff --git a/impeller/entity/shaders/gaussian_blur.frag b/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_nodecal.frag
similarity index 63%
copy from impeller/entity/shaders/gaussian_blur.frag
copy to impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_nodecal.frag
index 8b483ae..3c55695 100644
--- a/impeller/entity/shaders/gaussian_blur.frag
+++ b/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_nodecal.frag
@@ -2,10 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <impeller/texture.glsl>
-
-vec4 Sample(sampler2D tex, vec2 coords) {
-  return texture(tex, coords);
-}
+#define ENABLE_ALPHA_MASK 0
+#define ENABLE_DECAL_SPECIALIZATION 0
 
 #include "gaussian_blur.glsl"
diff --git a/impeller/entity/shaders/gaussian_blur_decal.frag b/impeller/entity/shaders/gaussian_blur_decal.frag
deleted file mode 100644
index c3076c7..0000000
--- a/impeller/entity/shaders/gaussian_blur_decal.frag
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <impeller/texture.glsl>
-
-vec4 Sample(sampler2D tex, vec2 coords) {
-  return IPSampleDecal(tex, coords);
-}
-
-#include "gaussian_blur.glsl"
diff --git a/impeller/tools/malioc.json b/impeller/tools/malioc.json
index 9d800cc..d9e3b4b 100644
--- a/impeller/tools/malioc.json
+++ b/impeller/tools/malioc.json
@@ -3154,78 +3154,6 @@
       }
     }
   },
-  "flutter/impeller/entity/gaussian_blur.frag.vkspv": {
-    "Mali-G78": {
-      "core": "Mali-G78",
-      "filename": "flutter/impeller/entity/gaussian_blur.frag.vkspv",
-      "has_side_effects": false,
-      "has_uniform_computation": true,
-      "modifies_coverage": false,
-      "reads_color_buffer": false,
-      "type": "Fragment",
-      "uses_late_zs_test": false,
-      "uses_late_zs_update": false,
-      "variants": {
-        "Main": {
-          "fp16_arithmetic": 47,
-          "has_stack_spilling": false,
-          "performance": {
-            "longest_path_bound_pipelines": [
-              null
-            ],
-            "longest_path_cycles": [
-              null,
-              null,
-              null,
-              null,
-              null,
-              null,
-              null
-            ],
-            "pipelines": [
-              "arith_total",
-              "arith_fma",
-              "arith_cvt",
-              "arith_sfu",
-              "load_store",
-              "varying",
-              "texture"
-            ],
-            "shortest_path_bound_pipelines": [
-              "varying",
-              "texture"
-            ],
-            "shortest_path_cycles": [
-              0.15625,
-              0.09375,
-              0.15625,
-              0.0625,
-              0.0,
-              0.25,
-              0.25
-            ],
-            "total_bound_pipelines": [
-              "varying",
-              "texture"
-            ],
-            "total_cycles": [
-              0.265625,
-              0.265625,
-              0.25,
-              0.125,
-              0.0,
-              0.5,
-              0.5
-            ]
-          },
-          "stack_spill_bytes": 0,
-          "thread_occupancy": 100,
-          "uniform_registers_used": 14,
-          "work_registers_used": 15
-        }
-      }
-    }
-  },
   "flutter/impeller/entity/gaussian_blur.vert.vkspv": {
     "Mali-G78": {
       "core": "Mali-G78",
@@ -3338,10 +3266,10 @@
       }
     }
   },
-  "flutter/impeller/entity/gaussian_blur_decal.frag.vkspv": {
+  "flutter/impeller/entity/gaussian_blur_alpha_decal.frag.vkspv": {
     "Mali-G78": {
       "core": "Mali-G78",
-      "filename": "flutter/impeller/entity/gaussian_blur_decal.frag.vkspv",
+      "filename": "flutter/impeller/entity/gaussian_blur_alpha_decal.frag.vkspv",
       "has_side_effects": false,
       "has_uniform_computation": true,
       "modifies_coverage": false,
@@ -3410,6 +3338,222 @@
       }
     }
   },
+  "flutter/impeller/entity/gaussian_blur_alpha_nodecal.frag.vkspv": {
+    "Mali-G78": {
+      "core": "Mali-G78",
+      "filename": "flutter/impeller/entity/gaussian_blur_alpha_nodecal.frag.vkspv",
+      "has_side_effects": false,
+      "has_uniform_computation": true,
+      "modifies_coverage": false,
+      "reads_color_buffer": false,
+      "type": "Fragment",
+      "uses_late_zs_test": false,
+      "uses_late_zs_update": false,
+      "variants": {
+        "Main": {
+          "fp16_arithmetic": 47,
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null,
+              null,
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arith_total",
+              "arith_fma",
+              "arith_cvt",
+              "arith_sfu",
+              "load_store",
+              "varying",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "varying",
+              "texture"
+            ],
+            "shortest_path_cycles": [
+              0.15625,
+              0.09375,
+              0.15625,
+              0.0625,
+              0.0,
+              0.25,
+              0.25
+            ],
+            "total_bound_pipelines": [
+              "varying",
+              "texture"
+            ],
+            "total_cycles": [
+              0.265625,
+              0.265625,
+              0.25,
+              0.125,
+              0.0,
+              0.5,
+              0.5
+            ]
+          },
+          "stack_spill_bytes": 0,
+          "thread_occupancy": 100,
+          "uniform_registers_used": 14,
+          "work_registers_used": 15
+        }
+      }
+    }
+  },
+  "flutter/impeller/entity/gaussian_blur_noalpha_decal.frag.vkspv": {
+    "Mali-G78": {
+      "core": "Mali-G78",
+      "filename": "flutter/impeller/entity/gaussian_blur_noalpha_decal.frag.vkspv",
+      "has_side_effects": false,
+      "has_uniform_computation": true,
+      "modifies_coverage": false,
+      "reads_color_buffer": false,
+      "type": "Fragment",
+      "uses_late_zs_test": false,
+      "uses_late_zs_update": false,
+      "variants": {
+        "Main": {
+          "fp16_arithmetic": 42,
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null,
+              null,
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arith_total",
+              "arith_fma",
+              "arith_cvt",
+              "arith_sfu",
+              "load_store",
+              "varying",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "arith_total",
+              "arith_cvt"
+            ],
+            "shortest_path_cycles": [
+              0.109375,
+              0.03125,
+              0.109375,
+              0.0625,
+              0.0,
+              0.0,
+              0.0
+            ],
+            "total_bound_pipelines": [
+              "arith_total",
+              "arith_sfu"
+            ],
+            "total_cycles": [
+              0.3125,
+              0.203125,
+              0.296875,
+              0.3125,
+              0.0,
+              0.25,
+              0.25
+            ]
+          },
+          "stack_spill_bytes": 0,
+          "thread_occupancy": 100,
+          "uniform_registers_used": 10,
+          "work_registers_used": 16
+        }
+      }
+    }
+  },
+  "flutter/impeller/entity/gaussian_blur_noalpha_nodecal.frag.vkspv": {
+    "Mali-G78": {
+      "core": "Mali-G78",
+      "filename": "flutter/impeller/entity/gaussian_blur_noalpha_nodecal.frag.vkspv",
+      "has_side_effects": false,
+      "has_uniform_computation": true,
+      "modifies_coverage": false,
+      "reads_color_buffer": false,
+      "type": "Fragment",
+      "uses_late_zs_test": false,
+      "uses_late_zs_update": false,
+      "variants": {
+        "Main": {
+          "fp16_arithmetic": 35,
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null,
+              null,
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arith_total",
+              "arith_fma",
+              "arith_cvt",
+              "arith_sfu",
+              "load_store",
+              "varying",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "arith_total",
+              "arith_cvt"
+            ],
+            "shortest_path_cycles": [
+              0.109375,
+              0.03125,
+              0.109375,
+              0.0625,
+              0.0,
+              0.0,
+              0.0
+            ],
+            "total_bound_pipelines": [
+              "varying",
+              "texture"
+            ],
+            "total_cycles": [
+              0.203125,
+              0.203125,
+              0.203125,
+              0.125,
+              0.0,
+              0.25,
+              0.25
+            ]
+          },
+          "stack_spill_bytes": 0,
+          "thread_occupancy": 100,
+          "uniform_registers_used": 10,
+          "work_registers_used": 13
+        }
+      }
+    }
+  },
   "flutter/impeller/entity/gles/advanced_blend.vert.gles": {
     "Mali-G78": {
       "core": "Mali-G78",
@@ -6322,123 +6466,6 @@
       }
     }
   },
-  "flutter/impeller/entity/gles/gaussian_blur.frag.gles": {
-    "Mali-G78": {
-      "core": "Mali-G78",
-      "filename": "flutter/impeller/entity/gles/gaussian_blur.frag.gles",
-      "has_side_effects": false,
-      "has_uniform_computation": true,
-      "modifies_coverage": false,
-      "reads_color_buffer": false,
-      "type": "Fragment",
-      "uses_late_zs_test": false,
-      "uses_late_zs_update": false,
-      "variants": {
-        "Main": {
-          "fp16_arithmetic": 76,
-          "has_stack_spilling": false,
-          "performance": {
-            "longest_path_bound_pipelines": [
-              null
-            ],
-            "longest_path_cycles": [
-              null,
-              null,
-              null,
-              null,
-              null,
-              null,
-              null
-            ],
-            "pipelines": [
-              "arith_total",
-              "arith_fma",
-              "arith_cvt",
-              "arith_sfu",
-              "load_store",
-              "varying",
-              "texture"
-            ],
-            "shortest_path_bound_pipelines": [
-              "varying",
-              "texture"
-            ],
-            "shortest_path_cycles": [
-              0.109375,
-              0.109375,
-              0.09375,
-              0.0625,
-              0.0,
-              0.25,
-              0.25
-            ],
-            "total_bound_pipelines": [
-              "varying",
-              "texture"
-            ],
-            "total_cycles": [
-              0.3125,
-              0.3125,
-              0.21875,
-              0.125,
-              0.0,
-              0.5,
-              0.5
-            ]
-          },
-          "stack_spill_bytes": 0,
-          "thread_occupancy": 100,
-          "uniform_registers_used": 12,
-          "work_registers_used": 21
-        }
-      }
-    },
-    "Mali-T880": {
-      "core": "Mali-T880",
-      "filename": "flutter/impeller/entity/gles/gaussian_blur.frag.gles",
-      "has_uniform_computation": false,
-      "type": "Fragment",
-      "variants": {
-        "Main": {
-          "has_stack_spilling": false,
-          "performance": {
-            "longest_path_bound_pipelines": [
-              null
-            ],
-            "longest_path_cycles": [
-              null,
-              null,
-              null
-            ],
-            "pipelines": [
-              "arithmetic",
-              "load_store",
-              "texture"
-            ],
-            "shortest_path_bound_pipelines": [
-              "arithmetic"
-            ],
-            "shortest_path_cycles": [
-              2.9700000286102295,
-              2.0,
-              1.0
-            ],
-            "total_bound_pipelines": [
-              "arithmetic"
-            ],
-            "total_cycles": [
-              5.0,
-              2.0,
-              2.0
-            ]
-          },
-          "thread_occupancy": 100,
-          "uniform_registers_used": 2,
-          "work_registers_used": 3
-        }
-      }
-    }
-  },
   "flutter/impeller/entity/gles/gaussian_blur.vert.gles": {
     "Mali-G78": {
       "core": "Mali-G78",
@@ -6596,10 +6623,10 @@
       }
     }
   },
-  "flutter/impeller/entity/gles/gaussian_blur_decal.frag.gles": {
+  "flutter/impeller/entity/gles/gaussian_blur_alpha_decal.frag.gles": {
     "Mali-G78": {
       "core": "Mali-G78",
-      "filename": "flutter/impeller/entity/gles/gaussian_blur_decal.frag.gles",
+      "filename": "flutter/impeller/entity/gles/gaussian_blur_alpha_decal.frag.gles",
       "has_side_effects": false,
       "has_uniform_computation": true,
       "modifies_coverage": false,
@@ -6609,7 +6636,7 @@
       "uses_late_zs_update": false,
       "variants": {
         "Main": {
-          "fp16_arithmetic": 79,
+          "fp16_arithmetic": 63,
           "has_stack_spilling": false,
           "performance": {
             "longest_path_bound_pipelines": [
@@ -6635,13 +6662,14 @@
             ],
             "shortest_path_bound_pipelines": [
               "arith_total",
+              "arith_cvt",
               "arith_sfu",
               "varying"
             ],
             "shortest_path_cycles": [
               0.25,
-              0.109375,
-              0.1875,
+              0.171875,
+              0.25,
               0.25,
               0.0,
               0.25,
@@ -6655,8 +6683,8 @@
             ],
             "total_cycles": [
               0.5,
-              0.3125,
-              0.421875,
+              0.359375,
+              0.484375,
               0.5,
               0.0,
               0.5,
@@ -6665,14 +6693,14 @@
           },
           "stack_spill_bytes": 0,
           "thread_occupancy": 100,
-          "uniform_registers_used": 12,
+          "uniform_registers_used": 10,
           "work_registers_used": 21
         }
       }
     },
     "Mali-T880": {
       "core": "Mali-T880",
-      "filename": "flutter/impeller/entity/gles/gaussian_blur_decal.frag.gles",
+      "filename": "flutter/impeller/entity/gles/gaussian_blur_alpha_decal.frag.gles",
       "has_uniform_computation": false,
       "type": "Fragment",
       "variants": {
@@ -6696,7 +6724,7 @@
               "arithmetic"
             ],
             "shortest_path_cycles": [
-              4.289999961853027,
+              4.619999885559082,
               2.0,
               0.0
             ],
@@ -6704,7 +6732,7 @@
               "arithmetic"
             ],
             "total_cycles": [
-              8.333333015441895,
+              8.666666984558105,
               2.0,
               2.0
             ]
@@ -6716,6 +6744,357 @@
       }
     }
   },
+  "flutter/impeller/entity/gles/gaussian_blur_alpha_nodecal.frag.gles": {
+    "Mali-G78": {
+      "core": "Mali-G78",
+      "filename": "flutter/impeller/entity/gles/gaussian_blur_alpha_nodecal.frag.gles",
+      "has_side_effects": false,
+      "has_uniform_computation": true,
+      "modifies_coverage": false,
+      "reads_color_buffer": false,
+      "type": "Fragment",
+      "uses_late_zs_test": false,
+      "uses_late_zs_update": false,
+      "variants": {
+        "Main": {
+          "fp16_arithmetic": 58,
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null,
+              null,
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arith_total",
+              "arith_fma",
+              "arith_cvt",
+              "arith_sfu",
+              "load_store",
+              "varying",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "varying",
+              "texture"
+            ],
+            "shortest_path_cycles": [
+              0.171875,
+              0.171875,
+              0.109375,
+              0.0625,
+              0.0,
+              0.25,
+              0.25
+            ],
+            "total_bound_pipelines": [
+              "varying",
+              "texture"
+            ],
+            "total_cycles": [
+              0.359375,
+              0.359375,
+              0.234375,
+              0.125,
+              0.0,
+              0.5,
+              0.5
+            ]
+          },
+          "stack_spill_bytes": 0,
+          "thread_occupancy": 100,
+          "uniform_registers_used": 12,
+          "work_registers_used": 20
+        }
+      }
+    },
+    "Mali-T880": {
+      "core": "Mali-T880",
+      "filename": "flutter/impeller/entity/gles/gaussian_blur_alpha_nodecal.frag.gles",
+      "has_uniform_computation": false,
+      "type": "Fragment",
+      "variants": {
+        "Main": {
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arithmetic",
+              "load_store",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "arithmetic"
+            ],
+            "shortest_path_cycles": [
+              3.299999952316284,
+              2.0,
+              1.0
+            ],
+            "total_bound_pipelines": [
+              "arithmetic"
+            ],
+            "total_cycles": [
+              5.333333492279053,
+              2.0,
+              2.0
+            ]
+          },
+          "thread_occupancy": 100,
+          "uniform_registers_used": 2,
+          "work_registers_used": 4
+        }
+      }
+    }
+  },
+  "flutter/impeller/entity/gles/gaussian_blur_noalpha_decal.frag.gles": {
+    "Mali-G78": {
+      "core": "Mali-G78",
+      "filename": "flutter/impeller/entity/gles/gaussian_blur_noalpha_decal.frag.gles",
+      "has_side_effects": false,
+      "has_uniform_computation": true,
+      "modifies_coverage": false,
+      "reads_color_buffer": false,
+      "type": "Fragment",
+      "uses_late_zs_test": false,
+      "uses_late_zs_update": false,
+      "variants": {
+        "Main": {
+          "fp16_arithmetic": 61,
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null,
+              null,
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arith_total",
+              "arith_fma",
+              "arith_cvt",
+              "arith_sfu",
+              "load_store",
+              "varying",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "arith_total",
+              "arith_cvt"
+            ],
+            "shortest_path_cycles": [
+              0.078125,
+              0.046875,
+              0.078125,
+              0.0625,
+              0.0,
+              0.0,
+              0.0
+            ],
+            "total_bound_pipelines": [
+              "arith_total",
+              "arith_sfu"
+            ],
+            "total_cycles": [
+              0.3125,
+              0.234375,
+              0.296875,
+              0.3125,
+              0.0,
+              0.25,
+              0.25
+            ]
+          },
+          "stack_spill_bytes": 0,
+          "thread_occupancy": 100,
+          "uniform_registers_used": 8,
+          "work_registers_used": 20
+        }
+      }
+    },
+    "Mali-T880": {
+      "core": "Mali-T880",
+      "filename": "flutter/impeller/entity/gles/gaussian_blur_noalpha_decal.frag.gles",
+      "has_uniform_computation": false,
+      "type": "Fragment",
+      "variants": {
+        "Main": {
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arithmetic",
+              "load_store",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "arithmetic"
+            ],
+            "shortest_path_cycles": [
+              2.9700000286102295,
+              1.0,
+              0.0
+            ],
+            "total_bound_pipelines": [
+              "arithmetic"
+            ],
+            "total_cycles": [
+              6.666666507720947,
+              1.0,
+              1.0
+            ]
+          },
+          "thread_occupancy": 100,
+          "uniform_registers_used": 1,
+          "work_registers_used": 4
+        }
+      }
+    }
+  },
+  "flutter/impeller/entity/gles/gaussian_blur_noalpha_nodecal.frag.gles": {
+    "Mali-G78": {
+      "core": "Mali-G78",
+      "filename": "flutter/impeller/entity/gles/gaussian_blur_noalpha_nodecal.frag.gles",
+      "has_side_effects": false,
+      "has_uniform_computation": true,
+      "modifies_coverage": false,
+      "reads_color_buffer": false,
+      "type": "Fragment",
+      "uses_late_zs_test": false,
+      "uses_late_zs_update": false,
+      "variants": {
+        "Main": {
+          "fp16_arithmetic": 57,
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null,
+              null,
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arith_total",
+              "arith_fma",
+              "arith_cvt",
+              "arith_sfu",
+              "load_store",
+              "varying",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "arith_total",
+              "arith_cvt"
+            ],
+            "shortest_path_cycles": [
+              0.078125,
+              0.046875,
+              0.078125,
+              0.0625,
+              0.0,
+              0.0,
+              0.0
+            ],
+            "total_bound_pipelines": [
+              "varying",
+              "texture"
+            ],
+            "total_cycles": [
+              0.234375,
+              0.234375,
+              0.203125,
+              0.125,
+              0.0,
+              0.25,
+              0.25
+            ]
+          },
+          "stack_spill_bytes": 0,
+          "thread_occupancy": 100,
+          "uniform_registers_used": 8,
+          "work_registers_used": 20
+        }
+      }
+    },
+    "Mali-T880": {
+      "core": "Mali-T880",
+      "filename": "flutter/impeller/entity/gles/gaussian_blur_noalpha_nodecal.frag.gles",
+      "has_uniform_computation": false,
+      "type": "Fragment",
+      "variants": {
+        "Main": {
+          "has_stack_spilling": false,
+          "performance": {
+            "longest_path_bound_pipelines": [
+              null
+            ],
+            "longest_path_cycles": [
+              null,
+              null,
+              null
+            ],
+            "pipelines": [
+              "arithmetic",
+              "load_store",
+              "texture"
+            ],
+            "shortest_path_bound_pipelines": [
+              "arithmetic"
+            ],
+            "shortest_path_cycles": [
+              2.309999942779541,
+              1.0,
+              0.0
+            ],
+            "total_bound_pipelines": [
+              "arithmetic"
+            ],
+            "total_cycles": [
+              4.333333492279053,
+              1.0,
+              1.0
+            ]
+          },
+          "thread_occupancy": 100,
+          "uniform_registers_used": 1,
+          "work_registers_used": 4
+        }
+      }
+    }
+  },
   "flutter/impeller/entity/gles/glyph_atlas.frag.gles": {
     "Mali-G78": {
       "core": "Mali-G78",