Revert "Cherry picks for image decoding in Impeller (#42362)"

This reverts commit c47096f618f3f667659e70e08f65dc454016afea.
diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm
index 105da47..4c912e9 100644
--- a/impeller/renderer/backend/metal/render_pass_mtl.mm
+++ b/impeller/renderer/backend/metal/render_pass_mtl.mm
@@ -383,13 +383,10 @@
   }
 
   if (texture.NeedsMipmapGeneration()) {
-    // TODO(127697): generate mips when the GPU is available on iOS.
-#if !FML_OS_IOS
     VALIDATION_LOG
         << "Texture at binding index " << bind_index
         << " has a mip count > 1, but the mipmap has not been generated.";
     return false;
-#endif  // !FML_OS_IOS
   }
 
   return pass.SetTexture(stage, bind_index,
diff --git a/lib/ui/fixtures/ui_test.dart b/lib/ui/fixtures/ui_test.dart
index 0bfd261..36f09bf 100644
--- a/lib/ui/fixtures/ui_test.dart
+++ b/lib/ui/fixtures/ui_test.dart
@@ -248,12 +248,12 @@
 external void _validatePath(Path path);
 
 @pragma('vm:entry-point')
-void frameCallback(Object? image, int durationMilliseconds, String decodeError) {
-  validateFrameCallback(image, durationMilliseconds, decodeError);
+void frameCallback(Object? image, int durationMilliseconds) {
+  validateFrameCallback(image, durationMilliseconds);
 }
 
 @pragma('vm:external-name', 'ValidateFrameCallback')
-external void validateFrameCallback(Object? image, int durationMilliseconds, String decodeError);
+external void validateFrameCallback(Object? image, int durationMilliseconds);
 
 @pragma('vm:entry-point')
 void platformMessagePortResponseTest() async {
diff --git a/lib/ui/painting.dart b/lib/ui/painting.dart
index a769937..8cbacfc 100644
--- a/lib/ui/painting.dart
+++ b/lib/ui/painting.dart
@@ -2105,12 +2105,9 @@
   /// [FrameInfo.image] on the returned object.
   Future<FrameInfo> getNextFrame() async {
     final Completer<FrameInfo> completer = Completer<FrameInfo>.sync();
-    final String? error = _getNextFrame((_Image? image, int durationMilliseconds, String decodeError) {
+    final String? error = _getNextFrame((_Image? image, int durationMilliseconds) {
       if (image == null) {
-        if (decodeError.isEmpty) {
-          decodeError = 'Codec failed to produce an image, possibly due to invalid image data.';
-        }
-        completer.completeError(Exception(decodeError));
+        completer.completeError(Exception('Codec failed to produce an image, possibly due to invalid image data.'));
       } else {
         completer.complete(FrameInfo._(
           image: Image._(image, image.width, image.height),
@@ -2126,7 +2123,7 @@
 
   /// Returns an error message on failure, null on success.
   @Native<Handle Function(Pointer<Void>, Handle)>(symbol: 'Codec::getNextFrame')
-  external String? _getNextFrame(void Function(_Image?, int, String) callback);
+  external String? _getNextFrame(void Function(_Image?, int) callback);
 
   /// Release the resources used by this object. The object is no longer usable
   /// after this method is called.
diff --git a/lib/ui/painting/image_decoder.cc b/lib/ui/painting/image_decoder.cc
index b598de3..905ffe4 100644
--- a/lib/ui/painting/image_decoder.cc
+++ b/lib/ui/painting/image_decoder.cc
@@ -16,16 +16,14 @@
     const Settings& settings,
     const TaskRunners& runners,
     std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
-    fml::WeakPtr<IOManager> io_manager,
-    const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) {
+    fml::WeakPtr<IOManager> io_manager) {
 #if IMPELLER_SUPPORTS_RENDERING
   if (settings.enable_impeller) {
     return std::make_unique<ImageDecoderImpeller>(
         runners,                            //
         std::move(concurrent_task_runner),  //
         std::move(io_manager),              //
-        settings.enable_wide_gamut,         //
-        gpu_disabled_switch);
+        settings.enable_wide_gamut);
   }
 #endif  // IMPELLER_SUPPORTS_RENDERING
   return std::make_unique<ImageDecoderSkia>(
diff --git a/lib/ui/painting/image_decoder.h b/lib/ui/painting/image_decoder.h
index ebb104e..0d4f18e 100644
--- a/lib/ui/painting/image_decoder.h
+++ b/lib/ui/painting/image_decoder.h
@@ -27,12 +27,11 @@
       const Settings& settings,
       const TaskRunners& runners,
       std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
-      fml::WeakPtr<IOManager> io_manager,
-      const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
+      fml::WeakPtr<IOManager> io_manager);
 
   virtual ~ImageDecoder();
 
-  using ImageResult = std::function<void(sk_sp<DlImage>, std::string)>;
+  using ImageResult = std::function<void(sk_sp<DlImage>)>;
 
   // Takes an image descriptor and returns a handle to a texture resident on the
   // GPU. All image decompression and resizes are done on a worker thread
diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc
index fdaf81a..4db68ac 100644
--- a/lib/ui/painting/image_decoder_impeller.cc
+++ b/lib/ui/painting/image_decoder_impeller.cc
@@ -79,11 +79,9 @@
     const TaskRunners& runners,
     std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
     const fml::WeakPtr<IOManager>& io_manager,
-    bool supports_wide_gamut,
-    const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
+    bool supports_wide_gamut)
     : ImageDecoder(runners, std::move(concurrent_task_runner), io_manager),
-      supports_wide_gamut_(supports_wide_gamut),
-      gpu_disabled_switch_(gpu_disabled_switch) {
+      supports_wide_gamut_(supports_wide_gamut) {
   std::promise<std::shared_ptr<impeller::Context>> context_promise;
   context_ = context_promise.get_future();
   runners_.GetIOTaskRunner()->PostTask(fml::MakeCopyable(
@@ -124,7 +122,7 @@
   return std::nullopt;
 }
 
-DecompressResult ImageDecoderImpeller::DecompressTexture(
+std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
     ImageDescriptor* descriptor,
     SkISize target_size,
     impeller::ISize max_texture_size,
@@ -132,9 +130,8 @@
     const std::shared_ptr<impeller::Allocator>& allocator) {
   TRACE_EVENT0("impeller", __FUNCTION__);
   if (!descriptor) {
-    std::string decode_error("Invalid descriptor (should never happen)");
-    FML_DLOG(ERROR) << decode_error;
-    return DecompressResult{.decode_error = decode_error};
+    FML_DLOG(ERROR) << "Invalid descriptor.";
+    return std::nullopt;
   }
 
   target_size.set(std::min(static_cast<int32_t>(max_texture_size.width),
@@ -179,11 +176,8 @@
 
   const auto pixel_format = ToPixelFormat(image_info.colorType());
   if (!pixel_format.has_value()) {
-    std::string decode_error(impeller::SPrintF(
-        "Codec pixel format is not supported (SkColorType=%d)",
-        image_info.colorType()));
-    FML_DLOG(ERROR) << decode_error;
-    return DecompressResult{.decode_error = decode_error};
+    FML_DLOG(ERROR) << "Codec pixel format not supported by Impeller.";
+    return std::nullopt;
   }
 
   auto bitmap = std::make_shared<SkBitmap>();
@@ -192,16 +186,14 @@
 
   if (descriptor->is_compressed()) {
     if (!bitmap->tryAllocPixels(bitmap_allocator.get())) {
-      std::string decode_error(
-          "Could not allocate intermediate for image decompression.");
-      FML_DLOG(ERROR) << decode_error;
-      return DecompressResult{.decode_error = decode_error};
+      FML_DLOG(ERROR)
+          << "Could not allocate intermediate for image decompression.";
+      return std::nullopt;
     }
     // Decode the image into the image generator's closest supported size.
     if (!descriptor->get_pixels(bitmap->pixmap())) {
-      std::string decode_error("Could not decompress image.");
-      FML_DLOG(ERROR) << decode_error;
-      return DecompressResult{.decode_error = decode_error};
+      FML_DLOG(ERROR) << "Could not decompress image.";
+      return std::nullopt;
     }
   } else {
     auto temp_bitmap = std::make_shared<SkBitmap>();
@@ -211,10 +203,9 @@
     temp_bitmap->setPixelRef(pixel_ref, 0, 0);
 
     if (!bitmap->tryAllocPixels(bitmap_allocator.get())) {
-      std::string decode_error(
-          "Could not allocate intermediate for pixel conversion.");
-      FML_DLOG(ERROR) << decode_error;
-      return DecompressResult{.decode_error = decode_error};
+      FML_DLOG(ERROR)
+          << "Could not allocate intermediate for pixel conversion.";
+      return std::nullopt;
     }
     temp_bitmap->readPixels(bitmap->pixmap());
     bitmap->setImmutable();
@@ -223,7 +214,7 @@
   if (bitmap->dimensions() == target_size) {
     auto buffer = bitmap_allocator->GetDeviceBuffer();
     if (!buffer.has_value()) {
-      return DecompressResult{.decode_error = "Unable to get device buffer"};
+      return std::nullopt;
     }
     return DecompressResult{.device_buffer = buffer.value(),
                             .sk_bitmap = bitmap,
@@ -241,10 +232,9 @@
   auto scaled_allocator = std::make_shared<ImpellerAllocator>(allocator);
   scaled_bitmap->setInfo(scaled_image_info);
   if (!scaled_bitmap->tryAllocPixels(scaled_allocator.get())) {
-    std::string decode_error(
-        "Could not allocate scaled bitmap for image decompression.");
-    FML_DLOG(ERROR) << decode_error;
-    return DecompressResult{.decode_error = decode_error};
+    FML_LOG(ERROR)
+        << "Could not allocate scaled bitmap for image decompression.";
+    return std::nullopt;
   }
   if (!bitmap->pixmap().scalePixels(
           scaled_bitmap->pixmap(),
@@ -255,31 +245,25 @@
 
   auto buffer = scaled_allocator->GetDeviceBuffer();
   if (!buffer.has_value()) {
-    return DecompressResult{.decode_error = "Unable to get device buffer"};
+    return std::nullopt;
   }
   return DecompressResult{.device_buffer = buffer.value(),
                           .sk_bitmap = scaled_bitmap,
                           .image_info = scaled_bitmap->info()};
 }
 
-/// Only call this method if the GPU is available.
-static std::pair<sk_sp<DlImage>, std::string> UnsafeUploadTextureToPrivate(
+sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate(
     const std::shared_ptr<impeller::Context>& context,
     const std::shared_ptr<impeller::DeviceBuffer>& buffer,
     const SkImageInfo& image_info) {
   TRACE_EVENT0("impeller", __FUNCTION__);
-  if (!context) {
-    return std::make_pair(nullptr, "No Impeller context is available");
-  }
-  if (!buffer) {
-    return std::make_pair(nullptr, "No Impeller device buffer is available");
+  if (!context || !buffer) {
+    return nullptr;
   }
   const auto pixel_format = ToPixelFormat(image_info.colorType());
   if (!pixel_format) {
-    std::string decode_error(impeller::SPrintF(
-        "Unsupported pixel format (SkColorType=%d)", image_info.colorType()));
-    FML_DLOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_DLOG(ERROR) << "Pixel format unsupported by Impeller.";
+    return nullptr;
   }
 
   impeller::TextureDescriptor texture_descriptor;
@@ -292,9 +276,8 @@
   auto dest_texture =
       context->GetResourceAllocator()->CreateTexture(texture_descriptor);
   if (!dest_texture) {
-    std::string decode_error("Could not create Impeller texture.");
-    FML_DLOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_DLOG(ERROR) << "Could not create Impeller texture.";
+    return nullptr;
   }
 
   dest_texture->SetLabel(
@@ -302,19 +285,15 @@
 
   auto command_buffer = context->CreateCommandBuffer();
   if (!command_buffer) {
-    std::string decode_error(
-        "Could not create command buffer for mipmap generation.");
-    FML_DLOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_DLOG(ERROR) << "Could not create command buffer for mipmap generation.";
+    return nullptr;
   }
   command_buffer->SetLabel("Mipmap Command Buffer");
 
   auto blit_pass = command_buffer->CreateBlitPass();
   if (!blit_pass) {
-    std::string decode_error(
-        "Could not create blit pass for mipmap generation.");
-    FML_DLOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_DLOG(ERROR) << "Could not create blit pass for mipmap generation.";
+    return nullptr;
   }
   blit_pass->SetLabel("Mipmap Blit Pass");
   blit_pass->AddCopy(buffer->AsBufferView(), dest_texture);
@@ -324,64 +303,26 @@
 
   blit_pass->EncodeCommands(context->GetResourceAllocator());
   if (!command_buffer->SubmitCommands()) {
-    std::string decode_error("Failed to submit blit pass command buffer.");
-    FML_DLOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_DLOG(ERROR) << "Failed to submit blit pass command buffer.";
+    return nullptr;
   }
 
-  return std::make_pair(
-      impeller::DlImageImpeller::Make(std::move(dest_texture)), std::string());
+  return impeller::DlImageImpeller::Make(std::move(dest_texture));
 }
 
-std::pair<sk_sp<DlImage>, std::string>
-ImageDecoderImpeller::UploadTextureToPrivate(
-    const std::shared_ptr<impeller::Context>& context,
-    const std::shared_ptr<impeller::DeviceBuffer>& buffer,
-    const SkImageInfo& image_info,
-    std::shared_ptr<SkBitmap> bitmap,
-    const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) {
-  TRACE_EVENT0("impeller", __FUNCTION__);
-  if (!context) {
-    return std::make_pair(nullptr, "No Impeller context is available");
-  }
-  if (!buffer) {
-    return std::make_pair(nullptr, "No Impeller device buffer is available");
-  }
-
-  std::pair<sk_sp<DlImage>, std::string> result;
-  gpu_disabled_switch->Execute(
-      fml::SyncSwitch::Handlers()
-          .SetIfFalse([&result, context, buffer, image_info] {
-            result = UnsafeUploadTextureToPrivate(context, buffer, image_info);
-          })
-          .SetIfTrue([&result, context, bitmap, gpu_disabled_switch] {
-            // create_mips is false because we already know the GPU is disabled.
-            result = UploadTextureToShared(context, bitmap, gpu_disabled_switch,
-                                           /*create_mips=*/false);
-          }));
-  return result;
-}
-
-std::pair<sk_sp<DlImage>, std::string>
-ImageDecoderImpeller::UploadTextureToShared(
+sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared(
     const std::shared_ptr<impeller::Context>& context,
     std::shared_ptr<SkBitmap> bitmap,
-    const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch,
     bool create_mips) {
   TRACE_EVENT0("impeller", __FUNCTION__);
-  if (!context) {
-    return std::make_pair(nullptr, "No Impeller context is available");
-  }
-  if (!bitmap) {
-    return std::make_pair(nullptr, "No texture bitmap is available");
+  if (!context || !bitmap) {
+    return nullptr;
   }
   const auto image_info = bitmap->info();
   const auto pixel_format = ToPixelFormat(image_info.colorType());
   if (!pixel_format) {
-    std::string decode_error(impeller::SPrintF(
-        "Unsupported pixel format (SkColorType=%d)", image_info.colorType()));
-    FML_DLOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_DLOG(ERROR) << "Pixel format unsupported by Impeller.";
+    return nullptr;
   }
 
   impeller::TextureDescriptor texture_descriptor;
@@ -394,9 +335,8 @@
   auto texture =
       context->GetResourceAllocator()->CreateTexture(texture_descriptor);
   if (!texture) {
-    std::string decode_error("Could not create Impeller texture.");
-    FML_DLOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_DLOG(ERROR) << "Could not create Impeller texture.";
+    return nullptr;
   }
 
   auto mapping = std::make_shared<fml::NonOwnedMapping>(
@@ -406,51 +346,37 @@
   );
 
   if (!texture->SetContents(mapping)) {
-    std::string decode_error("Could not copy contents into Impeller texture.");
-    FML_DLOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_DLOG(ERROR) << "Could not copy contents into Impeller texture.";
+    return nullptr;
   }
 
   texture->SetLabel(impeller::SPrintF("ui.Image(%p)", texture.get()).c_str());
 
   if (texture_descriptor.mip_count > 1u && create_mips) {
-    std::optional<std::string> decode_error;
+    auto command_buffer = context->CreateCommandBuffer();
+    if (!command_buffer) {
+      FML_DLOG(ERROR)
+          << "Could not create command buffer for mipmap generation.";
+      return nullptr;
+    }
+    command_buffer->SetLabel("Mipmap Command Buffer");
 
-    // The only platform that needs mipmapping unconditionally is GL.
-    // GL based platforms never disable GPU access.
-    // This is only really needed for iOS.
-    gpu_disabled_switch->Execute(fml::SyncSwitch::Handlers().SetIfFalse(
-        [context, &texture, &decode_error] {
-          auto command_buffer = context->CreateCommandBuffer();
-          if (!command_buffer) {
-            decode_error =
-                "Could not create command buffer for mipmap generation.";
-            return;
-          }
-          command_buffer->SetLabel("Mipmap Command Buffer");
+    auto blit_pass = command_buffer->CreateBlitPass();
+    if (!blit_pass) {
+      FML_DLOG(ERROR) << "Could not create blit pass for mipmap generation.";
+      return nullptr;
+    }
+    blit_pass->SetLabel("Mipmap Blit Pass");
+    blit_pass->GenerateMipmap(texture);
 
-          auto blit_pass = command_buffer->CreateBlitPass();
-          if (!blit_pass) {
-            decode_error = "Could not create blit pass for mipmap generation.";
-            return;
-          }
-          blit_pass->SetLabel("Mipmap Blit Pass");
-          blit_pass->GenerateMipmap(texture);
-
-          blit_pass->EncodeCommands(context->GetResourceAllocator());
-          if (!command_buffer->SubmitCommands()) {
-            decode_error = "Failed to submit blit pass command buffer.";
-            return;
-          }
-        }));
-    if (decode_error.has_value()) {
-      FML_DLOG(ERROR) << decode_error.value();
-      return std::make_pair(nullptr, decode_error.value());
+    blit_pass->EncodeCommands(context->GetResourceAllocator());
+    if (!command_buffer->SubmitCommands()) {
+      FML_DLOG(ERROR) << "Failed to submit blit pass command buffer.";
+      return nullptr;
     }
   }
 
-  return std::make_pair(impeller::DlImageImpeller::Make(std::move(texture)),
-                        std::string());
+  return impeller::DlImageImpeller::Make(std::move(texture));
 }
 
 // |ImageDecoder|
@@ -467,10 +393,10 @@
   ImageResult result = [p_result,                               //
                         raw_descriptor,                         //
                         ui_runner = runners_.GetUITaskRunner()  //
-  ](auto image, auto decode_error) {
-    ui_runner->PostTask([raw_descriptor, p_result, image, decode_error]() {
+  ](auto image) {
+    ui_runner->PostTask([raw_descriptor, p_result, image]() {
       raw_descriptor->Release();
-      p_result(std::move(image), decode_error);
+      p_result(std::move(image));
     });
   };
 
@@ -480,10 +406,10 @@
        target_size = SkISize::Make(target_width, target_height),  //
        io_runner = runners_.GetIOTaskRunner(),                    //
        result,
-       supports_wide_gamut = supports_wide_gamut_,  //
-       gpu_disabled_switch = gpu_disabled_switch_]() {
+       supports_wide_gamut = supports_wide_gamut_  //
+  ]() {
         if (!context) {
-          result(nullptr, "No Impeller context is available");
+          result(nullptr);
           return;
         }
         auto max_size_supported =
@@ -493,32 +419,25 @@
         auto bitmap_result = DecompressTexture(
             raw_descriptor, target_size, max_size_supported,
             supports_wide_gamut, context->GetResourceAllocator());
-        if (!bitmap_result.device_buffer) {
-          result(nullptr, bitmap_result.decode_error);
+        if (!bitmap_result.has_value()) {
+          result(nullptr);
           return;
         }
-        auto upload_texture_and_invoke_result = [result, context, bitmap_result,
-                                                 gpu_disabled_switch]() {
-          // TODO(jonahwilliams): remove ifdef once blit from buffer
-          // to texture is implemented on other platforms.
-          sk_sp<DlImage> image;
-          std::string decode_error;
-
+        auto upload_texture_and_invoke_result = [result, context,
+                                                 bitmap_result =
+                                                     bitmap_result.value()]() {
+// TODO(jonahwilliams): remove ifdef once blit from buffer to texture is
+// implemented on other platforms.
 #ifdef FML_OS_IOS
-          std::tie(image, decode_error) = UploadTextureToPrivate(
-              context, bitmap_result.device_buffer, bitmap_result.image_info,
-              bitmap_result.sk_bitmap, gpu_disabled_switch);
+          result(UploadTextureToPrivate(context, bitmap_result.device_buffer,
+                                        bitmap_result.image_info));
 #else
-          std::tie(image, decode_error) =
-              UploadTextureToShared(context, bitmap_result.sk_bitmap,
-                                    gpu_disabled_switch, /*create_mips=*/true);
-#endif  // FML_OS_IOS
-          result(image, decode_error);
+          result(UploadTextureToShared(context, bitmap_result.sk_bitmap));
+#endif
         };
-        // TODO(jonahwilliams):
-        // https://github.com/flutter/flutter/issues/123058 Technically we
-        // don't need to post tasks to the io runner, but without this
-        // forced serialization we can end up overloading the GPU and/or
+        // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/123058
+        // Technically we don't need to post tasks to the io runner, but without
+        // this forced serialization we can end up overloading the GPU and/or
         // competing with raster workloads.
         io_runner->PostTask(upload_texture_and_invoke_result);
       });
diff --git a/lib/ui/painting/image_decoder_impeller.h b/lib/ui/painting/image_decoder_impeller.h
index a9c1af4..9df6b22 100644
--- a/lib/ui/painting/image_decoder_impeller.h
+++ b/lib/ui/painting/image_decoder_impeller.h
@@ -41,7 +41,6 @@
   std::shared_ptr<impeller::DeviceBuffer> device_buffer;
   std::shared_ptr<SkBitmap> sk_bitmap;
   SkImageInfo image_info;
-  std::string decode_error;
 };
 
 class ImageDecoderImpeller final : public ImageDecoder {
@@ -50,8 +49,7 @@
       const TaskRunners& runners,
       std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
       const fml::WeakPtr<IOManager>& io_manager,
-      bool supports_wide_gamut,
-      const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
+      bool supports_wide_gamut);
 
   ~ImageDecoderImpeller() override;
 
@@ -61,7 +59,7 @@
               uint32_t target_height,
               const ImageResult& result) override;
 
-  static DecompressResult DecompressTexture(
+  static std::optional<DecompressResult> DecompressTexture(
       ImageDescriptor* descriptor,
       SkISize target_size,
       impeller::ISize max_texture_size,
@@ -73,35 +71,27 @@
   /// @param context    The Impeller graphics context.
   /// @param buffer     A host buffer containing the image to be uploaded.
   /// @param image_info Format information about the particular image.
-  /// @param bitmap      A bitmap containg the image to be uploaded.
-  /// @param gpu_disabled_switch Whether the GPU is available command encoding.
   /// @return           A DlImage.
-  static std::pair<sk_sp<DlImage>, std::string> UploadTextureToPrivate(
+  static sk_sp<DlImage> UploadTextureToPrivate(
       const std::shared_ptr<impeller::Context>& context,
       const std::shared_ptr<impeller::DeviceBuffer>& buffer,
-      const SkImageInfo& image_info,
-      std::shared_ptr<SkBitmap> bitmap,
-      const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
+      const SkImageInfo& image_info);
 
   /// @brief Create a host visible texture from the provided bitmap.
   /// @param context     The Impeller graphics context.
   /// @param bitmap      A bitmap containg the image to be uploaded.
   /// @param create_mips Whether mipmaps should be generated for the given
   /// image.
-  /// @param gpu_disabled_switch Whether the GPU is available for mipmap
-  /// creation.
   /// @return            A DlImage.
-  static std::pair<sk_sp<DlImage>, std::string> UploadTextureToShared(
+  static sk_sp<DlImage> UploadTextureToShared(
       const std::shared_ptr<impeller::Context>& context,
       std::shared_ptr<SkBitmap> bitmap,
-      const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch,
       bool create_mips = true);
 
  private:
   using FutureContext = std::shared_future<std::shared_ptr<impeller::Context>>;
   FutureContext context_;
   const bool supports_wide_gamut_;
-  std::shared_ptr<fml::SyncSwitch> gpu_disabled_switch_;
 
   FML_DISALLOW_COPY_AND_ASSIGN(ImageDecoderImpeller);
 };
diff --git a/lib/ui/painting/image_decoder_skia.cc b/lib/ui/painting/image_decoder_skia.cc
index 2cb609e..e1145c1 100644
--- a/lib/ui/painting/image_decoder_skia.cc
+++ b/lib/ui/painting/image_decoder_skia.cc
@@ -254,7 +254,7 @@
               // terminate without a base trace. Add one explicitly.
               TRACE_EVENT0("flutter", "ImageDecodeCallback");
               flow.End();
-              callback(DlImageGPU::Make(std::move(image)), {});
+              callback(DlImageGPU::Make(std::move(image)));
               raw_descriptor->Release();
             }));
       };
diff --git a/lib/ui/painting/image_decoder_unittests.cc b/lib/ui/painting/image_decoder_unittests.cc
index 13cefc6..0cc5165 100644
--- a/lib/ui/painting/image_decoder_unittests.cc
+++ b/lib/ui/painting/image_decoder_unittests.cc
@@ -136,12 +136,9 @@
   }
 
   std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override {
-    command_buffer_count_ += 1;
     return nullptr;
   }
 
-  mutable size_t command_buffer_count_ = 0;
-
  private:
   std::shared_ptr<const Capabilities> capabilities_;
 };
@@ -281,8 +278,7 @@
     TestIOManager manager(runners.GetIOTaskRunner());
     Settings settings;
     auto decoder = ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
-                                      manager.GetWeakIOManager(),
-                                      std::make_shared<fml::SyncSwitch>());
+                                      manager.GetWeakIOManager());
     ASSERT_NE(decoder, nullptr);
   });
 }
@@ -333,8 +329,7 @@
     TestIOManager manager(runners.GetIOTaskRunner());
     Settings settings;
     auto decoder = ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
-                                      manager.GetWeakIOManager(),
-                                      std::make_shared<fml::SyncSwitch>());
+                                      manager.GetWeakIOManager());
 
     auto data = OpenFixtureAsSkData("ThisDoesNotExist.jpg");
     ASSERT_FALSE(data);
@@ -343,8 +338,7 @@
         fml::MakeRefCounted<ImageDescriptor>(
             std::move(data), std::make_unique<UnknownImageGenerator>());
 
-    ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image,
-                                             const std::string& decode_error) {
+    ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image) {
       ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
       ASSERT_FALSE(image);
       latch.Signal();
@@ -373,9 +367,9 @@
   };
   auto decode_image = [&]() {
     Settings settings;
-    std::unique_ptr<ImageDecoder> image_decoder = ImageDecoder::Make(
-        settings, runners, loop->GetTaskRunner(),
-        io_manager->GetWeakIOManager(), std::make_shared<fml::SyncSwitch>());
+    std::unique_ptr<ImageDecoder> image_decoder =
+        ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
+                           io_manager->GetWeakIOManager());
 
     auto data = OpenFixtureAsSkData("DashInNooglerHat.jpg");
 
@@ -390,8 +384,7 @@
     auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
         std::move(data), std::move(generator));
 
-    ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image,
-                                             const std::string& decode_error) {
+    ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image) {
       ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
       ASSERT_TRUE(image && image->skia_image());
       EXPECT_TRUE(io_manager->did_access_is_gpu_disabled_sync_switch_);
@@ -429,34 +422,6 @@
 }
 }  // namespace
 
-TEST_F(ImageDecoderFixtureTest, ImpellerUploadToSharedNoGpu) {
-#if !IMPELLER_SUPPORTS_RENDERING
-  GTEST_SKIP() << "Impeller only test.";
-#endif  // IMPELLER_SUPPORTS_RENDERING
-
-  auto no_gpu_access_context =
-      std::make_shared<impeller::TestImpellerContext>();
-  auto gpu_disabled_switch = std::make_shared<fml::SyncSwitch>(true);
-
-  auto info = SkImageInfo::Make(10, 10, SkColorType::kRGBA_8888_SkColorType,
-                                SkAlphaType::kPremul_SkAlphaType);
-  auto bitmap = std::make_shared<SkBitmap>();
-  bitmap->allocPixels(info, 10 * 4);
-  impeller::DeviceBufferDescriptor desc;
-  desc.size = bitmap->computeByteSize();
-  auto buffer = std::make_shared<impeller::TestImpellerDeviceBuffer>(desc);
-
-  auto result = ImageDecoderImpeller::UploadTextureToPrivate(
-      no_gpu_access_context, buffer, info, bitmap, gpu_disabled_switch);
-  ASSERT_EQ(no_gpu_access_context->command_buffer_count_, 0ul);
-  ASSERT_EQ(result.second, "");
-
-  result = ImageDecoderImpeller::UploadTextureToShared(
-      no_gpu_access_context, bitmap, gpu_disabled_switch, true);
-  ASSERT_EQ(no_gpu_access_context->command_buffer_count_, 0ul);
-  ASSERT_EQ(result.second, "");
-}
-
 TEST_F(ImageDecoderFixtureTest, ImpellerNullColorspace) {
   auto info = SkImageInfo::Make(10, 10, SkColorType::kRGBA_8888_SkColorType,
                                 SkAlphaType::kPremul_SkAlphaType);
@@ -673,9 +638,9 @@
   SkISize decoded_size = SkISize::MakeEmpty();
   auto decode_image = [&]() {
     Settings settings;
-    std::unique_ptr<ImageDecoder> image_decoder = ImageDecoder::Make(
-        settings, runners, loop->GetTaskRunner(),
-        io_manager->GetWeakIOManager(), std::make_shared<fml::SyncSwitch>());
+    std::unique_ptr<ImageDecoder> image_decoder =
+        ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
+                           io_manager->GetWeakIOManager());
 
     auto data = OpenFixtureAsSkData("Horizontal.jpg");
 
@@ -690,8 +655,7 @@
     auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
         std::move(data), std::move(generator));
 
-    ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image,
-                                             const std::string& decode_error) {
+    ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image) {
       ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
       ASSERT_TRUE(image && image->skia_image());
       decoded_size = image->skia_image()->dimensions();
@@ -734,9 +698,9 @@
 
   auto decode_image = [&]() {
     Settings settings;
-    std::unique_ptr<ImageDecoder> image_decoder = ImageDecoder::Make(
-        settings, runners, loop->GetTaskRunner(),
-        io_manager->GetWeakIOManager(), std::make_shared<fml::SyncSwitch>());
+    std::unique_ptr<ImageDecoder> image_decoder =
+        ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
+                           io_manager->GetWeakIOManager());
 
     auto data = OpenFixtureAsSkData("DashInNooglerHat.jpg");
 
@@ -751,8 +715,7 @@
     auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
         std::move(data), std::move(generator));
 
-    ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image,
-                                             const std::string& decode_error) {
+    ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image) {
       ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
       ASSERT_TRUE(image && image->skia_image());
       runners.GetIOTaskRunner()->PostTask(release_io_manager);
@@ -802,8 +765,7 @@
   PostTaskSync(runners.GetUITaskRunner(), [&]() {
     Settings settings;
     image_decoder = ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
-                                       io_manager->GetWeakIOManager(),
-                                       std::make_shared<fml::SyncSwitch>());
+                                       io_manager->GetWeakIOManager());
   });
 
   // Setup a generic decoding utility that gives us the final decoded size.
@@ -824,13 +786,12 @@
       auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
           std::move(data), std::move(generator));
 
-      ImageDecoder::ImageResult callback =
-          [&](const sk_sp<DlImage>& image, const std::string& decode_error) {
-            ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
-            ASSERT_TRUE(image && image->skia_image());
-            final_size = image->skia_image()->dimensions();
-            latch.Signal();
-          };
+      ImageDecoder::ImageResult callback = [&](const sk_sp<DlImage>& image) {
+        ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
+        ASSERT_TRUE(image && image->skia_image());
+        final_size = image->skia_image()->dimensions();
+        latch.Signal();
+      };
       image_decoder->Decode(descriptor, target_width, target_height, callback);
     });
     latch.Wait();
@@ -896,14 +857,12 @@
   auto result_1 = ImageDecoderImpeller::DecompressTexture(
       descriptor.get(), SkISize::Make(6, 2), {100, 100},
       /*supports_wide_gamut=*/false, allocator);
-  ASSERT_EQ(result_1.sk_bitmap->width(), 6);
-  ASSERT_EQ(result_1.sk_bitmap->height(), 2);
+  ASSERT_EQ(result_1->sk_bitmap->dimensions(), SkISize::Make(6, 2));
 
   auto result_2 = ImageDecoderImpeller::DecompressTexture(
       descriptor.get(), SkISize::Make(60, 20), {10, 10},
       /*supports_wide_gamut=*/false, allocator);
-  ASSERT_EQ(result_2.sk_bitmap->width(), 10);
-  ASSERT_EQ(result_2.sk_bitmap->height(), 10);
+  ASSERT_EQ(result_2->sk_bitmap->dimensions(), SkISize::Make(10, 10));
 #endif  // IMPELLER_SUPPORTS_RENDERING
 }
 
@@ -931,13 +890,13 @@
   ASSERT_TRUE(expected_data != nullptr);
   ASSERT_FALSE(expected_data->isEmpty());
 
-  auto assert_image = [&](auto decoded_image, const std::string& decode_error) {
+  auto assert_image = [&](auto decoded_image) {
     ASSERT_EQ(decoded_image->dimensions(), SkISize::Make(300, 100));
     ASSERT_TRUE(decoded_image->encodeToData(SkEncodedImageFormat::kPNG, 100)
                     ->equals(expected_data.get()));
   };
 
-  assert_image(decode(300, 100), {});
+  assert_image(decode(300, 100));
 }
 
 TEST_F(ImageDecoderFixtureTest,
diff --git a/lib/ui/painting/multi_frame_codec.cc b/lib/ui/painting/multi_frame_codec.cc
index 21ac7b3..796ea46 100644
--- a/lib/ui/painting/multi_frame_codec.cc
+++ b/lib/ui/painting/multi_frame_codec.cc
@@ -38,7 +38,6 @@
 static void InvokeNextFrameCallback(
     const fml::RefPtr<CanvasImage>& image,
     int duration,
-    const std::string& decode_error,
     std::unique_ptr<DartPersistentValue> callback,
     size_t trace_id) {
   std::shared_ptr<tonic::DartState> dart_state = callback->dart_state().lock();
@@ -49,8 +48,7 @@
   }
   tonic::DartState::Scope scope(dart_state);
   tonic::DartInvoke(callback->value(),
-                    {tonic::ToDart(image), tonic::ToDart(duration),
-                     tonic::ToDart(decode_error)});
+                    {tonic::ToDart(image), tonic::ToDart(duration)});
 }
 
 // Copied the source bitmap to the destination. If this cannot occur due to
@@ -86,8 +84,7 @@
   return true;
 }
 
-std::pair<sk_sp<DlImage>, std::string>
-MultiFrameCodec::State::GetNextFrameImage(
+sk_sp<DlImage> MultiFrameCodec::State::GetNextFrameImage(
     fml::WeakPtr<GrDirectContext> resourceContext,
     const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch,
     const std::shared_ptr<impeller::Context>& impeller_context,
@@ -99,12 +96,9 @@
     info = updated;
   }
   if (!bitmap.tryAllocPixels(info)) {
-    std::ostringstream ostr;
-    ostr << "Failed to allocate memory for bitmap of size "
-         << info.computeMinByteSize() << "B";
-    std::string decode_error = ostr.str();
-    FML_LOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_LOG(ERROR) << "Failed to allocate memory for bitmap of size "
+                   << info.computeMinByteSize() << "B";
+    return nullptr;
   }
 
   ImageGenerator::FrameInfo frameInfo =
@@ -138,11 +132,8 @@
   // are already set in accordance with the previous frame's disposal policy.
   if (!generator_->GetPixels(info, bitmap.getPixels(), bitmap.rowBytes(),
                              nextFrameIndex_, requiredFrameIndex)) {
-    std::ostringstream ostr;
-    ostr << "Could not getPixels for frame " << nextFrameIndex_;
-    std::string decode_error = ostr.str();
-    FML_LOG(ERROR) << decode_error;
-    return std::make_pair(nullptr, decode_error);
+    FML_LOG(ERROR) << "Could not getPixels for frame " << nextFrameIndex_;
+    return nullptr;
   }
 
   // Hold onto this if we need it to decode future frames.
@@ -158,7 +149,6 @@
     // without mipmap creation there is no command buffer encoding done.
     return ImageDecoderImpeller::UploadTextureToShared(
         impeller_context, std::make_shared<SkBitmap>(bitmap),
-        std::make_shared<fml::SyncSwitch>(),
         /*create_mips=*/false);
   }
 #endif  // IMPELLER_SUPPORTS_RENDERING
@@ -186,8 +176,7 @@
             }
           }));
 
-  return std::make_pair(DlImageGPU::Make({skImage, std::move(unref_queue)}),
-                        std::string());
+  return DlImageGPU::Make({skImage, std::move(unref_queue)});
 }
 
 void MultiFrameCodec::State::GetNextFrameAndInvokeCallback(
@@ -200,9 +189,7 @@
     const std::shared_ptr<impeller::Context>& impeller_context) {
   fml::RefPtr<CanvasImage> image = nullptr;
   int duration = 0;
-  sk_sp<DlImage> dlImage;
-  std::string decode_error;
-  std::tie(dlImage, decode_error) =
+  sk_sp<DlImage> dlImage =
       GetNextFrameImage(std::move(resourceContext), gpu_disable_sync_switch,
                         impeller_context, std::move(unref_queue));
   if (dlImage) {
@@ -216,12 +203,11 @@
 
   // The static leak checker gets confused by the use of fml::MakeCopyable.
   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
-  ui_task_runner->PostTask(fml::MakeCopyable(
-      [callback = std::move(callback), image = std::move(image),
-       decode_error = std::move(decode_error), duration, trace_id]() mutable {
-        InvokeNextFrameCallback(image, duration, decode_error,
-                                std::move(callback), trace_id);
-      }));
+  ui_task_runner->PostTask(fml::MakeCopyable([callback = std::move(callback),
+                                              image = std::move(image),
+                                              duration, trace_id]() mutable {
+    InvokeNextFrameCallback(image, duration, std::move(callback), trace_id);
+  }));
 }
 
 Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle callback_handle) {
@@ -237,14 +223,12 @@
   const auto& task_runners = dart_state->GetTaskRunners();
 
   if (state_->frameCount_ == 0) {
-    std::string decode_error("Could not provide any frame.");
-    FML_LOG(ERROR) << decode_error;
+    FML_LOG(ERROR) << "Could not provide any frame.";
     task_runners.GetUITaskRunner()->PostTask(fml::MakeCopyable(
-        [trace_id, decode_error = std::move(decode_error),
+        [trace_id,
          callback = std::make_unique<DartPersistentValue>(
              tonic::DartState::Current(), callback_handle)]() mutable {
-          InvokeNextFrameCallback(nullptr, 0, decode_error, std::move(callback),
-                                  trace_id);
+          InvokeNextFrameCallback(nullptr, 0, std::move(callback), trace_id);
         }));
     return Dart_Null();
   }
diff --git a/lib/ui/painting/multi_frame_codec.h b/lib/ui/painting/multi_frame_codec.h
index a5f6acf..f569bbd 100644
--- a/lib/ui/painting/multi_frame_codec.h
+++ b/lib/ui/painting/multi_frame_codec.h
@@ -9,8 +9,6 @@
 #include "flutter/lib/ui/painting/codec.h"
 #include "flutter/lib/ui/painting/image_generator.h"
 
-#include <utility>
-
 using tonic::DartPersistentValue;
 
 namespace flutter {
@@ -58,7 +56,7 @@
     // The index of the last decoded required frame.
     int lastRequiredFrameIndex_ = -1;
 
-    std::pair<sk_sp<DlImage>, std::string> GetNextFrameImage(
+    sk_sp<DlImage> GetNextFrameImage(
         fml::WeakPtr<GrDirectContext> resourceContext,
         const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch,
         const std::shared_ptr<impeller::Context>& impeller_context,
diff --git a/lib/ui/painting/single_frame_codec.cc b/lib/ui/painting/single_frame_codec.cc
index 758cc56..e962b40 100644
--- a/lib/ui/painting/single_frame_codec.cc
+++ b/lib/ui/painting/single_frame_codec.cc
@@ -36,8 +36,8 @@
     if (!cached_image_->image()) {
       return tonic::ToDart("Decoded image has been disposed");
     }
-    tonic::DartInvoke(callback_handle, {tonic::ToDart(cached_image_),
-                                        tonic::ToDart(0), tonic::ToDart("")});
+    tonic::DartInvoke(callback_handle,
+                      {tonic::ToDart(cached_image_), tonic::ToDart(0)});
     return Dart_Null();
   }
 
@@ -69,8 +69,7 @@
       new fml::RefPtr<SingleFrameCodec>(this);
 
   decoder->Decode(
-      descriptor_, target_width_, target_height_,
-      [raw_codec_ref](auto image, auto decode_error) {
+      descriptor_, target_width_, target_height_, [raw_codec_ref](auto image) {
         std::unique_ptr<fml::RefPtr<SingleFrameCodec>> codec_ref(raw_codec_ref);
         fml::RefPtr<SingleFrameCodec> codec(std::move(*codec_ref));
 
@@ -98,9 +97,9 @@
 
         // Invoke any callbacks that were provided before the frame was decoded.
         for (const DartPersistentValue& callback : codec->pending_callbacks_) {
-          tonic::DartInvoke(callback.value(),
-                            {tonic::ToDart(codec->cached_image_),
-                             tonic::ToDart(0), tonic::ToDart(decode_error)});
+          tonic::DartInvoke(
+              callback.value(),
+              {tonic::ToDart(codec->cached_image_), tonic::ToDart(0)});
         }
         codec->pending_callbacks_.clear();
       });
diff --git a/shell/common/engine.cc b/shell/common/engine.cc
index 100449b..522ee89 100644
--- a/shell/common/engine.cc
+++ b/shell/common/engine.cc
@@ -45,8 +45,7 @@
     std::unique_ptr<Animator> animator,
     fml::WeakPtr<IOManager> io_manager,
     const std::shared_ptr<FontCollection>& font_collection,
-    std::unique_ptr<RuntimeController> runtime_controller,
-    const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
+    std::unique_ptr<RuntimeController> runtime_controller)
     : delegate_(delegate),
       settings_(settings),
       animator_(std::move(animator)),
@@ -55,8 +54,7 @@
       image_decoder_(ImageDecoder::Make(settings_,
                                         task_runners,
                                         std::move(image_decoder_task_runner),
-                                        std::move(io_manager),
-                                        gpu_disabled_switch)),
+                                        std::move(io_manager))),
       task_runners_(task_runners),
       weak_factory_(this) {
   pointer_data_dispatcher_ = dispatcher_maker(*this);
@@ -73,8 +71,7 @@
                fml::WeakPtr<IOManager> io_manager,
                fml::RefPtr<SkiaUnrefQueue> unref_queue,
                fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
-               std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
-               const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
+               std::shared_ptr<VolatilePathTracker> volatile_path_tracker)
     : Engine(delegate,
              dispatcher_maker,
              vm.GetConcurrentWorkerTaskRunner(),
@@ -83,8 +80,7 @@
              std::move(animator),
              io_manager,
              std::make_shared<FontCollection>(),
-             nullptr,
-             gpu_disabled_switch) {
+             nullptr) {
   runtime_controller_ = std::make_unique<RuntimeController>(
       *this,                                 // runtime delegate
       &vm,                                   // VM
@@ -116,8 +112,7 @@
     std::unique_ptr<Animator> animator,
     const std::string& initial_route,
     const fml::WeakPtr<IOManager>& io_manager,
-    fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
-    const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) const {
+    fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate) const {
   auto result = std::make_unique<Engine>(
       /*delegate=*/delegate,
       /*dispatcher_maker=*/dispatcher_maker,
@@ -128,8 +123,7 @@
       /*animator=*/std::move(animator),
       /*io_manager=*/io_manager,
       /*font_collection=*/font_collection_,
-      /*runtime_controller=*/nullptr,
-      /*gpu_disabled_switch=*/gpu_disabled_switch);
+      /*runtime_controller=*/nullptr);
   result->runtime_controller_ = runtime_controller_->Spawn(
       /*p_client=*/*result,
       /*advisory_script_uri=*/settings.advisory_script_uri,
diff --git a/shell/common/engine.h b/shell/common/engine.h
index f45ddd2..c6ff37e 100644
--- a/shell/common/engine.h
+++ b/shell/common/engine.h
@@ -309,8 +309,7 @@
          std::unique_ptr<Animator> animator,
          fml::WeakPtr<IOManager> io_manager,
          const std::shared_ptr<FontCollection>& font_collection,
-         std::unique_ptr<RuntimeController> runtime_controller,
-         const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
+         std::unique_ptr<RuntimeController> runtime_controller);
 
   //----------------------------------------------------------------------------
   /// @brief      Creates an instance of the engine. This is done by the Shell
@@ -365,8 +364,7 @@
          fml::WeakPtr<IOManager> io_manager,
          fml::RefPtr<SkiaUnrefQueue> unref_queue,
          fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
-         std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
-         const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
+         std::shared_ptr<VolatilePathTracker> volatile_path_tracker);
 
   //----------------------------------------------------------------------------
   /// @brief      Create a Engine that shares as many resources as
@@ -384,8 +382,7 @@
       std::unique_ptr<Animator> animator,
       const std::string& initial_route,
       const fml::WeakPtr<IOManager>& io_manager,
-      fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
-      const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) const;
+      fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate) const;
 
   //----------------------------------------------------------------------------
   /// @brief      Destroys the engine engine. Called by the shell on the UI task
diff --git a/shell/common/engine_unittests.cc b/shell/common/engine_unittests.cc
index 0848d79..3bfdd00 100644
--- a/shell/common/engine_unittests.cc
+++ b/shell/common/engine_unittests.cc
@@ -162,8 +162,7 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(runtime_controller_),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(runtime_controller_));
     EXPECT_TRUE(engine);
   });
 }
@@ -184,8 +183,7 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(mock_runtime_controller),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(mock_runtime_controller));
 
     fml::RefPtr<PlatformMessageResponse> response =
         fml::MakeRefCounted<MockResponse>();
@@ -211,8 +209,7 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(mock_runtime_controller),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(mock_runtime_controller));
 
     fml::RefPtr<PlatformMessageResponse> response =
         fml::MakeRefCounted<MockResponse>();
@@ -245,8 +242,7 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(mock_runtime_controller),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(mock_runtime_controller));
 
     fml::RefPtr<PlatformMessageResponse> response =
         fml::MakeRefCounted<MockResponse>();
@@ -278,12 +274,10 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(mock_runtime_controller),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(mock_runtime_controller));
 
-    auto spawn =
-        engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
-                      std::string(), io_manager_, snapshot_delegate_, nullptr);
+    auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
+                               std::string(), io_manager_, snapshot_delegate_);
     EXPECT_TRUE(spawn != nullptr);
     EXPECT_EQ(&engine->GetFontCollection(), &spawn->GetFontCollection());
   });
@@ -306,12 +300,10 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(mock_runtime_controller),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(mock_runtime_controller));
 
-    auto spawn =
-        engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr, "/foo",
-                      io_manager_, snapshot_delegate_, nullptr);
+    auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
+                               "/foo", io_manager_, snapshot_delegate_);
     EXPECT_TRUE(spawn != nullptr);
     ASSERT_EQ("/foo", spawn->InitialRoute());
   });
@@ -340,16 +332,14 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(mock_runtime_controller),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(mock_runtime_controller));
 
     auto& old_platform_data = engine->GetRuntimeController()->GetPlatformData();
     EXPECT_EQ(old_platform_data.viewport_metrics.physical_width, kViewWidth);
     EXPECT_EQ(old_platform_data.viewport_metrics.physical_height, kViewHeight);
 
-    auto spawn =
-        engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
-                      std::string(), io_manager_, snapshot_delegate_, nullptr);
+    auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
+                               std::string(), io_manager_, snapshot_delegate_);
     EXPECT_TRUE(spawn != nullptr);
     auto& new_viewport_metrics =
         spawn->GetRuntimeController()->GetPlatformData().viewport_metrics;
@@ -375,15 +365,14 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(mock_runtime_controller),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(mock_runtime_controller));
 
     Settings custom_settings = settings_;
     custom_settings.persistent_isolate_data =
         std::make_shared<fml::DataMapping>("foo");
     auto spawn =
         engine->Spawn(delegate_, dispatcher_maker_, custom_settings, nullptr,
-                      std::string(), io_manager_, snapshot_delegate_, nullptr);
+                      std::string(), io_manager_, snapshot_delegate_);
     EXPECT_TRUE(spawn != nullptr);
     auto new_persistent_isolate_data =
         const_cast<RuntimeController*>(spawn->GetRuntimeController())
@@ -416,8 +405,7 @@
         /*animator=*/std::move(animator_),
         /*io_manager=*/io_manager_,
         /*font_collection=*/std::make_shared<FontCollection>(),
-        /*runtime_controller=*/std::move(mock_runtime_controller),
-        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
+        /*runtime_controller=*/std::move(mock_runtime_controller));
 
     engine->LoadDartDeferredLibraryError(error_id, error_message, true);
   });
diff --git a/shell/common/fixtures/shell_test.dart b/shell/common/fixtures/shell_test.dart
index ffb42c3..0a4e5a6 100644
--- a/shell/common/fixtures/shell_test.dart
+++ b/shell/common/fixtures/shell_test.dart
@@ -326,7 +326,7 @@
 }
 
 @pragma('vm:entry-point')
-void frameCallback(Object? image, int durationMilliseconds, String decodeError) {
+void frameCallback(Object? image, int durationMilliseconds) {
   if (image == null) {
     throw Exception('Expeccted image in frame callback to be non-null');
   }
diff --git a/shell/common/shell.cc b/shell/common/shell.cc
index a6ad507..214b3b3 100644
--- a/shell/common/shell.cc
+++ b/shell/common/shell.cc
@@ -54,21 +54,19 @@
     const fml::WeakPtr<IOManager>& io_manager,
     const fml::RefPtr<SkiaUnrefQueue>& unref_queue,
     const fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>& snapshot_delegate,
-    const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker,
-    const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) {
-  return std::make_unique<Engine>(delegate,               //
-                                  dispatcher_maker,       //
-                                  vm,                     //
-                                  isolate_snapshot,       //
-                                  task_runners,           //
-                                  platform_data,          //
-                                  settings,               //
-                                  std::move(animator),    //
-                                  io_manager,             //
-                                  unref_queue,            //
-                                  snapshot_delegate,      //
-                                  volatile_path_tracker,  //
-                                  gpu_disabled_switch);
+    const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker) {
+  return std::make_unique<Engine>(delegate,             //
+                                  dispatcher_maker,     //
+                                  vm,                   //
+                                  isolate_snapshot,     //
+                                  task_runners,         //
+                                  platform_data,        //
+                                  settings,             //
+                                  std::move(animator),  //
+                                  io_manager,           //
+                                  unref_queue,          //
+                                  snapshot_delegate,    //
+                                  volatile_path_tracker);
 }
 
 // Though there can be multiple shells, some settings apply to all components in
@@ -303,8 +301,7 @@
                              weak_io_manager_future.get(),    //
                              unref_queue_future.get(),        //
                              snapshot_delegate_future.get(),  //
-                             shell->volatile_path_tracker_,
-                             shell->is_gpu_disabled_sync_switch_));
+                             shell->volatile_path_tracker_));
       }));
 
   if (!shell->Setup(std::move(platform_view),  //
@@ -541,8 +538,7 @@
           const fml::WeakPtr<IOManager>& io_manager,
           const fml::RefPtr<SkiaUnrefQueue>& unref_queue,
           fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
-          const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker,
-          const std::shared_ptr<fml::SyncSwitch>& is_gpu_disabled_sync_switch) {
+          const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker) {
         return engine->Spawn(
             /*delegate=*/delegate,
             /*dispatcher_maker=*/dispatcher_maker,
@@ -550,8 +546,7 @@
             /*animator=*/std::move(animator),
             /*initial_route=*/initial_route,
             /*io_manager=*/io_manager,
-            /*snapshot_delegate=*/std::move(snapshot_delegate),
-            /*gpu_disabled_switch=*/is_gpu_disabled_sync_switch);
+            /*snapshot_delegate=*/std::move(snapshot_delegate));
       },
       is_gpu_disabled);
   result->RunEngine(std::move(run_configuration));
diff --git a/shell/common/shell.h b/shell/common/shell.h
index 1b5d1bd..2ecf71d 100644
--- a/shell/common/shell.h
+++ b/shell/common/shell.h
@@ -126,8 +126,7 @@
       fml::WeakPtr<IOManager> io_manager,
       fml::RefPtr<SkiaUnrefQueue> unref_queue,
       fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
-      std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
-      const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)>
+      std::shared_ptr<VolatilePathTracker> volatile_path_tracker)>
       EngineCreateCallback;
 
   //----------------------------------------------------------------------------
@@ -357,7 +356,6 @@
 
   //----------------------------------------------------------------------------
   /// @brief     Accessor for the disable GPU SyncSwitch.
-  // |Rasterizer::Delegate|
   std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch()
       const override;