[Impeller] one aiks context per app. (#55393)

Hoist the content context up to the ios_surface so that overlay layers don't recreate a bunch of expensive machinery. 

Fixes https://github.com/flutter/flutter/issues/154836
diff --git a/shell/common/shell_test_platform_view_metal.mm b/shell/common/shell_test_platform_view_metal.mm
index 4132249..9434552 100644
--- a/shell/common/shell_test_platform_view_metal.mm
+++ b/shell/common/shell_test_platform_view_metal.mm
@@ -113,8 +113,9 @@
 // |PlatformView|
 std::unique_ptr<Surface> ShellTestPlatformViewMetal::CreateRenderingSurface() {
   if (GetSettings().enable_impeller) {
-    return std::make_unique<GPUSurfaceMetalImpeller>(this,
-                                                     [metal_context_->impeller_context() context]);
+    auto context = [metal_context_->impeller_context() context];
+    return std::make_unique<GPUSurfaceMetalImpeller>(
+        this, std::make_shared<impeller::AiksContext>(context, nullptr));
   }
   return std::make_unique<GPUSurfaceMetalSkia>(this, [metal_context_->context() mainContext]);
 }
diff --git a/shell/gpu/gpu_surface_metal_impeller.h b/shell/gpu/gpu_surface_metal_impeller.h
index 8933900..02407fd 100644
--- a/shell/gpu/gpu_surface_metal_impeller.h
+++ b/shell/gpu/gpu_surface_metal_impeller.h
@@ -21,7 +21,7 @@
     : public Surface {
  public:
   GPUSurfaceMetalImpeller(GPUSurfaceMetalDelegate* delegate,
-                          const std::shared_ptr<impeller::Context>& context,
+                          const std::shared_ptr<impeller::AiksContext>& context,
                           bool render_to_surface = true);
 
   // |Surface|
diff --git a/shell/gpu/gpu_surface_metal_impeller.mm b/shell/gpu/gpu_surface_metal_impeller.mm
index ff765af..79b6c20 100644
--- a/shell/gpu/gpu_surface_metal_impeller.mm
+++ b/shell/gpu/gpu_surface_metal_impeller.mm
@@ -8,6 +8,7 @@
 #import <QuartzCore/QuartzCore.h>
 #include "flow/surface.h"
 #include "flow/surface_frame.h"
+#include "impeller/aiks/aiks_context.h"
 
 #include "flutter/common/settings.h"
 #include "flutter/fml/make_copyable.h"
@@ -21,14 +22,13 @@
 
 namespace flutter {
 
-GPUSurfaceMetalImpeller::GPUSurfaceMetalImpeller(GPUSurfaceMetalDelegate* delegate,
-                                                 const std::shared_ptr<impeller::Context>& context,
-                                                 bool render_to_surface)
+GPUSurfaceMetalImpeller::GPUSurfaceMetalImpeller(
+    GPUSurfaceMetalDelegate* delegate,
+    const std::shared_ptr<impeller::AiksContext>& context,
+    bool render_to_surface)
     : delegate_(delegate),
       render_target_type_(delegate->GetRenderTargetType()),
-      aiks_context_(
-          std::make_shared<impeller::AiksContext>(context,
-                                                  impeller::TypographerContextSkia::Make())),
+      aiks_context_(context),
       render_to_surface_(render_to_surface) {
   // If this preference is explicitly set, we allow for disabling partial repaint.
   NSNumber* disablePartialRepaint =
@@ -167,12 +167,14 @@
         impeller::IRect cull_rect = surface->coverage();
         SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight());
         surface->SetFrameBoundary(surface_frame.submit_info().frame_boundary);
+
+        const bool reset_host_buffer = surface_frame.submit_info().frame_boundary;
         auto render_result =
             impeller::RenderToOnscreen(aiks_context->GetContentContext(),         //
                                        surface->GetTargetRenderPassDescriptor(),  //
                                        display_list,                              //
                                        sk_cull_rect,                              //
-                                       /*reset_host_buffer=*/true                 //
+                                       /*reset_host_buffer=*/reset_host_buffer    //
             );
         if (!render_result) {
           return false;
diff --git a/shell/gpu/gpu_surface_metal_impeller_unittests.mm b/shell/gpu/gpu_surface_metal_impeller_unittests.mm
index 1663227..4c37c83 100644
--- a/shell/gpu/gpu_surface_metal_impeller_unittests.mm
+++ b/shell/gpu/gpu_surface_metal_impeller_unittests.mm
@@ -7,10 +7,12 @@
 
 #include "flutter/shell/gpu/gpu_surface_metal_impeller.h"
 #include "gtest/gtest.h"
+#include "impeller/aiks/aiks_context.h"
 #include "impeller/entity/mtl/entity_shaders.h"
 #include "impeller/entity/mtl/framebuffer_blend_shaders.h"
 #include "impeller/entity/mtl/modern_shaders.h"
 #include "impeller/renderer/backend/metal/context_mtl.h"
+#include "impeller/typographer/typographer_context.h"
 
 namespace flutter {
 namespace testing {
@@ -64,15 +66,16 @@
 
 TEST(GPUSurfaceMetalImpeller, CanCreateValidSurface) {
   auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
-  auto surface = std::make_shared<GPUSurfaceMetalImpeller>(delegate.get(), CreateImpellerContext());
+  auto surface = std::make_shared<GPUSurfaceMetalImpeller>(
+      delegate.get(), std::make_shared<impeller::AiksContext>(CreateImpellerContext(), nullptr));
 
   ASSERT_TRUE(surface->IsValid());
 }
 
 TEST(GPUSurfaceMetalImpeller, AcquireFrameFromCAMetalLayerNullChecksDrawable) {
   auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
-  std::shared_ptr<Surface> surface =
-      std::make_shared<GPUSurfaceMetalImpeller>(delegate.get(), CreateImpellerContext());
+  std::shared_ptr<Surface> surface = std::make_shared<GPUSurfaceMetalImpeller>(
+      delegate.get(), std::make_shared<impeller::AiksContext>(CreateImpellerContext(), nullptr));
 
   ASSERT_TRUE(surface->IsValid());
 
@@ -83,8 +86,8 @@
 TEST(GPUSurfaceMetalImpeller, AcquireFrameFromCAMetalLayerDoesNotRetainThis) {
   auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
   delegate->SetDevice();
-  std::unique_ptr<Surface> surface =
-      std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), CreateImpellerContext());
+  std::unique_ptr<Surface> surface = std::make_unique<GPUSurfaceMetalImpeller>(
+      delegate.get(), std::make_shared<impeller::AiksContext>(CreateImpellerContext(), nullptr));
 
   ASSERT_TRUE(surface->IsValid());
 
@@ -97,14 +100,13 @@
   ASSERT_TRUE(frame->Submit());
 }
 
-// Because each overlay surface gets its own HostBuffer, we always need to reset.
-TEST(GPUSurfaceMetalImpeller, DoesNotResetHostBufferBasedOnFrameBoundary) {
+TEST(GPUSurfaceMetalImpeller, ResetHostBufferBasedOnFrameBoundary) {
   auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
   delegate->SetDevice();
 
   auto context = CreateImpellerContext();
-  std::unique_ptr<Surface> surface =
-      std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), context);
+  std::unique_ptr<Surface> surface = std::make_unique<GPUSurfaceMetalImpeller>(
+      delegate.get(), std::make_shared<impeller::AiksContext>(context, nullptr));
 
   ASSERT_TRUE(surface->IsValid());
 
@@ -116,13 +118,13 @@
   frame->set_submit_info({.frame_boundary = false});
 
   ASSERT_TRUE(frame->Submit());
-  EXPECT_EQ(host_buffer.GetStateForTest().current_frame, 1u);
+  EXPECT_EQ(host_buffer.GetStateForTest().current_frame, 0u);
 
   frame = surface->AcquireFrame(SkISize::Make(100, 100));
   frame->set_submit_info({.frame_boundary = true});
 
   ASSERT_TRUE(frame->Submit());
-  EXPECT_EQ(host_buffer.GetStateForTest().current_frame, 2u);
+  EXPECT_EQ(host_buffer.GetStateForTest().current_frame, 1u);
 }
 
 #ifdef IMPELLER_DEBUG
@@ -131,18 +133,19 @@
   delegate->SetDevice();
 
   auto context = CreateImpellerContext();
+  auto aiks_context = std::make_shared<impeller::AiksContext>(context, nullptr);
 
   EXPECT_FALSE(context->GetCaptureManager()->CaptureScopeActive());
 
   std::unique_ptr<Surface> surface =
-      std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), context);
+      std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), aiks_context);
   auto frame_1 = surface->AcquireFrame(SkISize::Make(100, 100));
   frame_1->set_submit_info({.frame_boundary = false});
 
   EXPECT_TRUE(context->GetCaptureManager()->CaptureScopeActive());
 
   std::unique_ptr<Surface> surface_2 =
-      std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), context);
+      std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), aiks_context);
   auto frame_2 = surface->AcquireFrame(SkISize::Make(100, 100));
   frame_2->set_submit_info({.frame_boundary = true});
 
diff --git a/shell/platform/darwin/ios/ios_context.h b/shell/platform/darwin/ios/ios_context.h
index ef9dcca..e2c789d 100644
--- a/shell/platform/darwin/ios/ios_context.h
+++ b/shell/platform/darwin/ios/ios_context.h
@@ -15,6 +15,7 @@
 #include "flutter/fml/synchronization/sync_switch.h"
 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
 #import "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
+#include "impeller/aiks/aiks_context.h"
 #include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
 
 namespace impeller {
@@ -140,6 +141,8 @@
 
   virtual std::shared_ptr<impeller::Context> GetImpellerContext() const;
 
+  virtual std::shared_ptr<impeller::AiksContext> GetAiksContext() const;
+
  protected:
   explicit IOSContext();
 
diff --git a/shell/platform/darwin/ios/ios_context.mm b/shell/platform/darwin/ios/ios_context.mm
index ac6db41..762847e 100644
--- a/shell/platform/darwin/ios/ios_context.mm
+++ b/shell/platform/darwin/ios/ios_context.mm
@@ -63,4 +63,8 @@
   return nullptr;
 }
 
+std::shared_ptr<impeller::AiksContext> IOSContext::GetAiksContext() const {
+  return nullptr;
+}
+
 }  // namespace flutter
diff --git a/shell/platform/darwin/ios/ios_context_metal_impeller.h b/shell/platform/darwin/ios/ios_context_metal_impeller.h
index 5e2ed7a..b5293da 100644
--- a/shell/platform/darwin/ios/ios_context_metal_impeller.h
+++ b/shell/platform/darwin/ios/ios_context_metal_impeller.h
@@ -9,6 +9,7 @@
 #include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h"
 #include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h"
 #include "flutter/shell/platform/darwin/ios/ios_context.h"
+#include "impeller/aiks/aiks_context.h"
 
 namespace impeller {
 
@@ -34,6 +35,7 @@
 
  private:
   fml::scoped_nsobject<FlutterDarwinContextMetalImpeller> darwin_context_metal_impeller_;
+  std::shared_ptr<impeller::AiksContext> aiks_context_;
 
   // |IOSContext|
   sk_sp<GrDirectContext> CreateResourceContext() override;
@@ -49,6 +51,9 @@
   // |IOSContext|
   std::shared_ptr<impeller::Context> GetImpellerContext() const override;
 
+  // |IOSContext|
+  std::shared_ptr<impeller::AiksContext> GetAiksContext() const override;
+
   FML_DISALLOW_COPY_AND_ASSIGN(IOSContextMetalImpeller);
 };
 
diff --git a/shell/platform/darwin/ios/ios_context_metal_impeller.mm b/shell/platform/darwin/ios/ios_context_metal_impeller.mm
index 92a59a8..b3846b1 100644
--- a/shell/platform/darwin/ios/ios_context_metal_impeller.mm
+++ b/shell/platform/darwin/ios/ios_context_metal_impeller.mm
@@ -3,8 +3,11 @@
 // found in the LICENSE file.
 
 #import "flutter/shell/platform/darwin/ios/ios_context_metal_impeller.h"
+
 #include "flutter/impeller/entity/mtl/entity_shaders.h"
 #import "flutter/shell/platform/darwin/ios/ios_external_texture_metal.h"
+#include "impeller/aiks/aiks_context.h"
+#include "impeller/typographer/backends/skia/typographer_context_skia.h"
 
 FLUTTER_ASSERT_ARC
 
@@ -13,7 +16,12 @@
 IOSContextMetalImpeller::IOSContextMetalImpeller(
     const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch)
     : darwin_context_metal_impeller_(fml::scoped_nsobject<FlutterDarwinContextMetalImpeller>{
-          [[FlutterDarwinContextMetalImpeller alloc] init:is_gpu_disabled_sync_switch]}) {}
+          [[FlutterDarwinContextMetalImpeller alloc] init:is_gpu_disabled_sync_switch]}) {
+  if (darwin_context_metal_impeller_.get().context) {
+    aiks_context_ = std::make_shared<impeller::AiksContext>(
+        darwin_context_metal_impeller_.get().context, impeller::TypographerContextSkia::Make());
+  }
+}
 
 IOSContextMetalImpeller::~IOSContextMetalImpeller() = default;
 
@@ -40,6 +48,11 @@
 }
 
 // |IOSContext|
+std::shared_ptr<impeller::AiksContext> IOSContextMetalImpeller::GetAiksContext() const {
+  return aiks_context_;
+}
+
+// |IOSContext|
 std::unique_ptr<GLContextResult> IOSContextMetalImpeller::MakeCurrent() {
   // This only makes sense for contexts that need to be bound to a specific thread.
   return std::make_unique<GLContextDefaultResult>(true);
diff --git a/shell/platform/darwin/ios/ios_surface.h b/shell/platform/darwin/ios/ios_surface.h
index 78394f2..96970a4 100644
--- a/shell/platform/darwin/ios/ios_surface.h
+++ b/shell/platform/darwin/ios/ios_surface.h
@@ -18,10 +18,6 @@
 
 namespace flutter {
 
-// Returns true if the app explicitly specified to use the iOS view embedding
-// mechanism which is still in a release preview.
-bool IsIosEmbeddedViewsPreviewEnabled();
-
 class IOSSurface {
  public:
   static std::unique_ptr<IOSSurface> Create(std::shared_ptr<IOSContext> context,
diff --git a/shell/platform/darwin/ios/ios_surface_metal_impeller.h b/shell/platform/darwin/ios/ios_surface_metal_impeller.h
index 888f393..86c5171 100644
--- a/shell/platform/darwin/ios/ios_surface_metal_impeller.h
+++ b/shell/platform/darwin/ios/ios_surface_metal_impeller.h
@@ -30,6 +30,7 @@
  private:
   fml::scoped_nsobject<CAMetalLayer> layer_;
   const std::shared_ptr<impeller::Context> impeller_context_;
+  std::shared_ptr<impeller::AiksContext> aiks_context_;
   bool is_valid_ = false;
 
   // |IOSSurface|
diff --git a/shell/platform/darwin/ios/ios_surface_metal_impeller.mm b/shell/platform/darwin/ios/ios_surface_metal_impeller.mm
index 8d1a75d..89b7e72 100644
--- a/shell/platform/darwin/ios/ios_surface_metal_impeller.mm
+++ b/shell/platform/darwin/ios/ios_surface_metal_impeller.mm
@@ -7,6 +7,9 @@
 #include "flutter/impeller/renderer/backend/metal/formats_mtl.h"
 #include "flutter/impeller/renderer/context.h"
 #include "flutter/shell/gpu/gpu_surface_metal_impeller.h"
+#include "impeller/aiks/aiks_context.h"
+#include "impeller/typographer/backends/skia/typographer_context_skia.h"
+#include "impeller/typographer/typographer_context.h"
 
 FLUTTER_ASSERT_ARC
 
@@ -17,8 +20,9 @@
     : IOSSurface(context),
       GPUSurfaceMetalDelegate(MTLRenderTargetType::kCAMetalLayer),
       layer_(layer),
-      impeller_context_(context ? context->GetImpellerContext() : nullptr) {
-  if (!impeller_context_) {
+      impeller_context_(context ? context->GetImpellerContext() : nullptr),
+      aiks_context_(context ? context->GetAiksContext() : nullptr) {
+  if (!impeller_context_ || !aiks_context_) {
     return;
   }
   is_valid_ = true;
@@ -41,8 +45,8 @@
 std::unique_ptr<Surface> IOSSurfaceMetalImpeller::CreateGPUSurface(GrDirectContext*) {
   impeller_context_->UpdateOffscreenLayerPixelFormat(
       impeller::FromMTLPixelFormat(layer_.get().pixelFormat));
-  return std::make_unique<GPUSurfaceMetalImpeller>(this,              //
-                                                   impeller_context_  //
+  return std::make_unique<GPUSurfaceMetalImpeller>(this,          //
+                                                   aiks_context_  //
   );
 }
 
diff --git a/shell/platform/embedder/embedder_surface_metal_impeller.h b/shell/platform/embedder/embedder_surface_metal_impeller.h
index 109870a..3589f7f 100644
--- a/shell/platform/embedder/embedder_surface_metal_impeller.h
+++ b/shell/platform/embedder/embedder_surface_metal_impeller.h
@@ -12,6 +12,7 @@
 #include "flutter/shell/platform/embedder/embedder_external_view_embedder.h"
 #include "flutter/shell/platform/embedder/embedder_surface.h"
 #include "fml/concurrent_message_loop.h"
+#include "impeller/aiks/aiks_context.h"
 
 namespace impeller {
 class Context;
@@ -41,6 +42,7 @@
   MetalDispatchTable metal_dispatch_table_;
   std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder_;
   std::shared_ptr<impeller::Context> context_;
+  std::shared_ptr<impeller::AiksContext> aiks_context_;
 
   // |EmbedderSurface|
   bool IsValid() const override;
diff --git a/shell/platform/embedder/embedder_surface_metal_impeller.mm b/shell/platform/embedder/embedder_surface_metal_impeller.mm
index d1d1265..6365388 100644
--- a/shell/platform/embedder/embedder_surface_metal_impeller.mm
+++ b/shell/platform/embedder/embedder_surface_metal_impeller.mm
@@ -12,10 +12,13 @@
 #include "flutter/shell/gpu/gpu_surface_metal_delegate.h"
 #include "flutter/shell/gpu/gpu_surface_metal_impeller.h"
 #import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h"
+#include "impeller/aiks/aiks_context.h"
 #include "impeller/entity/mtl/entity_shaders.h"
 #include "impeller/entity/mtl/framebuffer_blend_shaders.h"
 #include "impeller/entity/mtl/modern_shaders.h"
 #include "impeller/renderer/backend/metal/context_mtl.h"
+#include "impeller/typographer/backends/skia/typographer_context_skia.h"
+#include "impeller/typographer/typographer_context.h"
 
 FLUTTER_ASSERT_NOT_ARC
 
@@ -60,9 +63,13 @@
   if (!IsValid()) {
     return nullptr;
   }
+  if (!aiks_context_) {
+    aiks_context_ =
+        std::make_shared<impeller::AiksContext>(context_, impeller::TypographerContextSkia::Make());
+  }
 
   const bool render_to_surface = !external_view_embedder_;
-  auto surface = std::make_unique<GPUSurfaceMetalImpeller>(this, context_, render_to_surface);
+  auto surface = std::make_unique<GPUSurfaceMetalImpeller>(this, aiks_context_, render_to_surface);
 
   if (!surface->IsValid()) {
     return nullptr;