[Impeller] Don't make playgrounds implicitly be test fixtures. (#34957)

diff --git a/DEPS b/DEPS
index 9f405fc..14b3a90 100644
--- a/DEPS
+++ b/DEPS
@@ -102,7 +102,7 @@
 ]
 
 deps = {
-  'src': 'https://github.com/flutter/buildroot.git' + '@' + 'fd6e9d332eed84b2a9d2a0f790c24089bbc0a093',
+  'src': 'https://github.com/flutter/buildroot.git' + '@' + 'cd444824e34d8f735a351f680776bc0479f20677',
 
    # Fuchsia compatibility
    #
diff --git a/impeller/aiks/BUILD.gn b/impeller/aiks/BUILD.gn
index 03267c4..744e1a9 100644
--- a/impeller/aiks/BUILD.gn
+++ b/impeller/aiks/BUILD.gn
@@ -41,7 +41,7 @@
   deps = [
     ":aiks",
     "../geometry:geometry_unittests",
-    "../playground",
+    "../playground:playground_test",
     "//flutter/testing",
   ]
 }
diff --git a/impeller/aiks/aiks_playground.h b/impeller/aiks/aiks_playground.h
index dc88cb3..02647fa 100644
--- a/impeller/aiks/aiks_playground.h
+++ b/impeller/aiks/aiks_playground.h
@@ -7,11 +7,11 @@
 #include "flutter/fml/macros.h"
 #include "impeller/aiks/aiks_context.h"
 #include "impeller/aiks/picture.h"
-#include "impeller/playground/playground.h"
+#include "impeller/playground/playground_test.h"
 
 namespace impeller {
 
-class AiksPlayground : public Playground {
+class AiksPlayground : public PlaygroundTest {
  public:
   using AiksPlaygroundCallback =
       std::function<bool(AiksContext& renderer, RenderTarget& render_target)>;
diff --git a/impeller/display_list/BUILD.gn b/impeller/display_list/BUILD.gn
index 79d711c..a7a51ae 100644
--- a/impeller/display_list/BUILD.gn
+++ b/impeller/display_list/BUILD.gn
@@ -31,6 +31,6 @@
 
   deps = [
     ":display_list",
-    "../playground",
+    "../playground:playground_test",
   ]
 }
diff --git a/impeller/display_list/display_list_playground.h b/impeller/display_list/display_list_playground.h
index fac3aef..e4645c6 100644
--- a/impeller/display_list/display_list_playground.h
+++ b/impeller/display_list/display_list_playground.h
@@ -7,12 +7,12 @@
 #include "flutter/display_list/display_list.h"
 #include "flutter/display_list/display_list_builder.h"
 #include "flutter/fml/macros.h"
-#include "impeller/playground/playground.h"
+#include "impeller/playground/playground_test.h"
 #include "third_party/skia/include/core/SkFont.h"
 
 namespace impeller {
 
-class DisplayListPlayground : public Playground {
+class DisplayListPlayground : public PlaygroundTest {
  public:
   using DisplayListPlaygroundCallback =
       std::function<sk_sp<flutter::DisplayList>()>;
diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc
index e962caa..65207ec 100644
--- a/impeller/display_list/display_list_unittests.cc
+++ b/impeller/display_list/display_list_unittests.cc
@@ -8,12 +8,6 @@
 #include "display_list/display_list_image_filter.h"
 #include "display_list/display_list_paint.h"
 #include "display_list/display_list_tile_mode.h"
-#include "gtest/gtest.h"
-#include "third_party/imgui/imgui.h"
-#include "third_party/skia/include/core/SkClipOp.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkPathBuilder.h"
-
 #include "flutter/display_list/display_list_builder.h"
 #include "flutter/display_list/display_list_mask_filter.h"
 #include "flutter/display_list/types.h"
@@ -22,6 +16,10 @@
 #include "impeller/display_list/display_list_playground.h"
 #include "impeller/geometry/point.h"
 #include "impeller/playground/widgets.h"
+#include "third_party/imgui/imgui.h"
+#include "third_party/skia/include/core/SkClipOp.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPathBuilder.h"
 
 namespace impeller {
 namespace testing {
diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn
index 48dfab0..0c1dfef 100644
--- a/impeller/entity/BUILD.gn
+++ b/impeller/entity/BUILD.gn
@@ -121,6 +121,6 @@
   deps = [
     ":entity",
     "../geometry:geometry_unittests",
-    "../playground",
+    "../playground:playground_test",
   ]
 }
diff --git a/impeller/entity/entity_playground.h b/impeller/entity/entity_playground.h
index 68b6bad..c66e588 100644
--- a/impeller/entity/entity_playground.h
+++ b/impeller/entity/entity_playground.h
@@ -7,11 +7,11 @@
 #include "flutter/fml/macros.h"
 #include "impeller/entity/contents/content_context.h"
 #include "impeller/entity/entity.h"
-#include "impeller/playground/playground.h"
+#include "impeller/playground/playground_test.h"
 
 namespace impeller {
 
-class EntityPlayground : public Playground {
+class EntityPlayground : public PlaygroundTest {
  public:
   using EntityPlaygroundCallback =
       std::function<bool(ContentContext& context, RenderPass& pass)>;
diff --git a/impeller/playground/BUILD.gn b/impeller/playground/BUILD.gn
index 0ff76fb..104a042 100644
--- a/impeller/playground/BUILD.gn
+++ b/impeller/playground/BUILD.gn
@@ -6,8 +6,6 @@
 import("//flutter/testing/testing.gni")
 
 impeller_component("playground") {
-  testonly = true
-
   sources = [
     "playground.cc",
     "playground.h",
@@ -45,7 +43,7 @@
     "../fixtures:shader_fixtures",
     "../renderer",
     "imgui:imgui_impeller_backend",
-    "//flutter/testing",
+    "//flutter/fml",
     "//third_party/glfw",
     "//third_party/imgui:imgui_glfw",
   ]
@@ -60,6 +58,20 @@
   }
 }
 
+impeller_component("playground_test") {
+  testonly = true
+
+  sources = [
+    "playground_test.cc",
+    "playground_test.h",
+  ]
+
+  public_deps = [
+    ":playground",
+    "//flutter/testing",
+  ]
+}
+
 config("playground_config") {
   if (impeller_enable_playground) {
     defines = [ "IMPELLER_ENABLE_PLAYGROUND" ]
diff --git a/impeller/playground/imgui/BUILD.gn b/impeller/playground/imgui/BUILD.gn
index fcce7ae..3b0c53b 100644
--- a/impeller/playground/imgui/BUILD.gn
+++ b/impeller/playground/imgui/BUILD.gn
@@ -12,9 +12,7 @@
   ]
 }
 
-source_set("imgui_impeller_backend") {
-  testonly = true
-
+impeller_component("imgui_impeller_backend") {
   public_deps = [
     ":imgui_shaders",
     "//third_party/imgui",
diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc
index d2058ef..87a0895 100644
--- a/impeller/playground/playground.cc
+++ b/impeller/playground/playground.cc
@@ -14,7 +14,6 @@
 #include "third_party/glfw/include/GLFW/glfw3.h"
 
 #include "flutter/fml/paths.h"
-#include "flutter/testing/testing.h"
 #include "impeller/base/validation.h"
 #include "impeller/image/compressed_image.h"
 #include "impeller/playground/imgui/imgui_impl_impeller.h"
@@ -76,15 +75,11 @@
 
 Playground::~Playground() = default;
 
-PlaygroundBackend Playground::GetBackend() const {
-  return GetParam();
-}
-
 std::shared_ptr<Context> Playground::GetContext() const {
   return renderer_ ? renderer_->GetContext() : nullptr;
 }
 
-static constexpr bool PlatformSupportsBackend(PlaygroundBackend backend) {
+bool Playground::SupportsBackend(PlaygroundBackend backend) {
   switch (backend) {
     case PlaygroundBackend::kMetal:
 #if IMPELLER_ENABLE_METAL
@@ -108,12 +103,10 @@
   FML_UNREACHABLE();
 }
 
-void Playground::SetUp() {
-  if (!PlatformSupportsBackend(GetBackend())) {
-    GTEST_SKIP_("This backend is disabled or isn't supported on this platform");
-  }
+void Playground::SetupWindow(PlaygroundBackend backend) {
+  FML_CHECK(SupportsBackend(backend));
 
-  impl_ = PlaygroundImpl::Create(GetParam());
+  impl_ = PlaygroundImpl::Create(backend);
   if (!impl_) {
     return;
   }
@@ -128,7 +121,7 @@
   renderer_ = std::move(renderer);
 }
 
-void Playground::TearDown() {
+void Playground::TeardownWindow() {
   renderer_.reset();
   impl_.reset();
 }
@@ -143,13 +136,6 @@
   }
 }
 
-static std::string GetWindowTitle(const std::string& test_name) {
-  std::stringstream stream;
-  stream << "Impeller Playground for '" << test_name
-         << "' (Press ESC or 'q' to quit)";
-  return stream.str();
-}
-
 Point Playground::GetCursorPosition() const {
   return cursor_position_;
 }
@@ -190,8 +176,7 @@
   if (!window) {
     return false;
   }
-  ::glfwSetWindowTitle(
-      window, GetWindowTitle(flutter::testing::GetCurrentTestName()).c_str());
+  ::glfwSetWindowTitle(window, GetWindowTitle().c_str());
   ::glfwSetWindowUserPointer(window, this);
   ::glfwSetWindowSizeCallback(
       window, [](GLFWwindow* window, int width, int height) -> void {
@@ -309,12 +294,12 @@
 
 std::optional<DecompressedImage> Playground::LoadFixtureImageRGBA(
     const char* fixture_name) const {
-  if (!renderer_) {
+  if (!renderer_ || fixture_name == nullptr) {
     return std::nullopt;
   }
 
-  auto compressed_image = CompressedImage::Create(
-      flutter::testing::OpenFixtureAsMapping(fixture_name));
+  auto compressed_image =
+      CompressedImage::Create(OpenAssetAsMapping(fixture_name));
   if (!compressed_image) {
     VALIDATION_LOG << "Could not create compressed image.";
     return std::nullopt;
diff --git a/impeller/playground/playground.h b/impeller/playground/playground.h
index d5f8eb6..cbb38bd 100644
--- a/impeller/playground/playground.h
+++ b/impeller/playground/playground.h
@@ -8,7 +8,6 @@
 
 #include "flutter/fml/closure.h"
 #include "flutter/fml/macros.h"
-#include "gtest/gtest.h"
 #include "impeller/geometry/point.h"
 #include "impeller/renderer/renderer.h"
 #include "impeller/renderer/texture.h"
@@ -25,21 +24,19 @@
 
 std::string PlaygroundBackendToString(PlaygroundBackend backend);
 
-class Playground : public ::testing::TestWithParam<PlaygroundBackend> {
+class Playground {
  public:
   using SinglePassCallback = std::function<bool(RenderPass& pass)>;
 
-  Playground();
+  explicit Playground();
 
-  ~Playground();
+  virtual ~Playground();
 
   static constexpr bool is_enabled() { return is_enabled_; }
 
-  void SetUp() override;
+  void SetupWindow(PlaygroundBackend backend);
 
-  void TearDown() override;
-
-  PlaygroundBackend GetBackend() const;
+  void TeardownWindow();
 
   Point GetCursorPosition() const;
 
@@ -63,6 +60,13 @@
   std::shared_ptr<Texture> CreateTextureCubeForFixture(
       std::array<const char*, 6> fixture_names) const;
 
+  static bool SupportsBackend(PlaygroundBackend backend);
+
+  virtual std::unique_ptr<fml::Mapping> OpenAssetAsMapping(
+      std::string asset_name) const = 0;
+
+  virtual std::string GetWindowTitle() const = 0;
+
  private:
 #if IMPELLER_ENABLE_PLAYGROUND
   static const bool is_enabled_ = true;
@@ -84,14 +88,4 @@
   FML_DISALLOW_COPY_AND_ASSIGN(Playground);
 };
 
-#define INSTANTIATE_PLAYGROUND_SUITE(playground)                        \
-  INSTANTIATE_TEST_SUITE_P(                                             \
-      Play, playground,                                                 \
-      ::testing::Values(PlaygroundBackend::kMetal,                      \
-                        PlaygroundBackend::kOpenGLES,                   \
-                        PlaygroundBackend::kVulkan),                    \
-      [](const ::testing::TestParamInfo<Playground::ParamType>& info) { \
-        return PlaygroundBackendToString(info.param);                   \
-      });
-
 }  // namespace impeller
diff --git a/impeller/playground/playground_test.cc b/impeller/playground/playground_test.cc
new file mode 100644
index 0000000..3cb7c94
--- /dev/null
+++ b/impeller/playground/playground_test.cc
@@ -0,0 +1,44 @@
+// 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/playground/playground_test.h"
+
+namespace impeller {
+
+PlaygroundTest::PlaygroundTest() = default;
+
+PlaygroundTest::~PlaygroundTest() = default;
+
+void PlaygroundTest::SetUp() {
+  if (!Playground::SupportsBackend(GetParam())) {
+    GTEST_SKIP_("Playground doesn't support this backend type.");
+    return;
+  }
+
+  SetupWindow(GetParam());
+}
+
+void PlaygroundTest::TearDown() {
+  TeardownWindow();
+}
+
+// |Playground|
+std::unique_ptr<fml::Mapping> PlaygroundTest::OpenAssetAsMapping(
+    std::string asset_name) const {
+  return flutter::testing::OpenFixtureAsMapping(asset_name);
+}
+
+static std::string FormatWindowTitle(const std::string& test_name) {
+  std::stringstream stream;
+  stream << "Impeller Playground for '" << test_name
+         << "' (Press ESC or 'q' to quit)";
+  return stream.str();
+}
+
+// |Playground|
+std::string PlaygroundTest::GetWindowTitle() const {
+  return FormatWindowTitle(flutter::testing::GetCurrentTestName());
+}
+
+}  // namespace impeller
diff --git a/impeller/playground/playground_test.h b/impeller/playground/playground_test.h
new file mode 100644
index 0000000..2e10fae
--- /dev/null
+++ b/impeller/playground/playground_test.h
@@ -0,0 +1,47 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+
+#include "flutter/fml/macros.h"
+#include "flutter/testing/testing.h"
+#include "impeller/playground/playground.h"
+
+namespace impeller {
+
+class PlaygroundTest : public Playground,
+                       public ::testing::TestWithParam<PlaygroundBackend> {
+ public:
+  PlaygroundTest();
+
+  virtual ~PlaygroundTest();
+
+  void SetUp() override;
+
+  void TearDown() override;
+
+  // |Playground|
+  std::unique_ptr<fml::Mapping> OpenAssetAsMapping(
+      std::string asset_name) const override;
+
+  // |Playground|
+  std::string GetWindowTitle() const override;
+
+ private:
+  FML_DISALLOW_COPY_AND_ASSIGN(PlaygroundTest);
+};
+
+#define INSTANTIATE_PLAYGROUND_SUITE(playground)                            \
+  INSTANTIATE_TEST_SUITE_P(                                                 \
+      Play, playground,                                                     \
+      ::testing::Values(PlaygroundBackend::kMetal,                          \
+                        PlaygroundBackend::kOpenGLES,                       \
+                        PlaygroundBackend::kVulkan),                        \
+      [](const ::testing::TestParamInfo<PlaygroundTest::ParamType>& info) { \
+        return PlaygroundBackendToString(info.param);                       \
+      });
+
+}  // namespace impeller
diff --git a/impeller/renderer/BUILD.gn b/impeller/renderer/BUILD.gn
index ab659f9..9223f46 100644
--- a/impeller/renderer/BUILD.gn
+++ b/impeller/renderer/BUILD.gn
@@ -98,7 +98,7 @@
   deps = [
     ":renderer",
     "../fixtures",
-    "../playground",
+    "../playground:playground_test",
     "//flutter/testing:testing_lib",
   ]
 }
diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc
index f473a28..5131479 100644
--- a/impeller/renderer/renderer_unittests.cc
+++ b/impeller/renderer/renderer_unittests.cc
@@ -20,7 +20,7 @@
 #include "impeller/geometry/path_builder.h"
 #include "impeller/image/compressed_image.h"
 #include "impeller/image/decompressed_image.h"
-#include "impeller/playground/playground.h"
+#include "impeller/playground/playground_test.h"
 #include "impeller/renderer/command.h"
 #include "impeller/renderer/command_buffer.h"
 #include "impeller/renderer/formats.h"
@@ -38,7 +38,7 @@
 namespace impeller {
 namespace testing {
 
-using RendererTest = Playground;
+using RendererTest = PlaygroundTest;
 INSTANTIATE_PLAYGROUND_SUITE(RendererTest);
 
 TEST_P(RendererTest, CanCreateBoxPrimitive) {
@@ -384,7 +384,7 @@
 
 #if IMPELLER_ENABLE_METAL
 TEST_P(RendererTest, CanRenderInstanced) {
-  if (GetBackend() != PlaygroundBackend::kMetal) {
+  if (GetParam() != PlaygroundBackend::kMetal) {
     GTEST_SKIP_("Instancing is only supported on Metal.");
   }
   using VS = InstancedDrawVertexShader;
diff --git a/impeller/runtime_stage/BUILD.gn b/impeller/runtime_stage/BUILD.gn
index 7ebed6e..e0fe250 100644
--- a/impeller/runtime_stage/BUILD.gn
+++ b/impeller/runtime_stage/BUILD.gn
@@ -39,7 +39,7 @@
   ]
   deps = [
     ":runtime_stage",
-    "../playground",
+    "../playground:playground_test",
     "//flutter/testing",
   ]
 }
diff --git a/impeller/runtime_stage/runtime_stage_playground.h b/impeller/runtime_stage/runtime_stage_playground.h
index c97d008..0b4168b 100644
--- a/impeller/runtime_stage/runtime_stage_playground.h
+++ b/impeller/runtime_stage/runtime_stage_playground.h
@@ -5,12 +5,12 @@
 #pragma once
 
 #include "flutter/fml/macros.h"
-#include "impeller/playground/playground.h"
+#include "impeller/playground/playground_test.h"
 #include "impeller/runtime_stage/runtime_stage.h"
 
 namespace impeller {
 
-class RuntimeStagePlayground : public Playground {
+class RuntimeStagePlayground : public PlaygroundTest {
  public:
   RuntimeStagePlayground();
 
diff --git a/impeller/runtime_stage/runtime_stage_unittests.cc b/impeller/runtime_stage/runtime_stage_unittests.cc
index 00b0960..66e3a83 100644
--- a/impeller/runtime_stage/runtime_stage_unittests.cc
+++ b/impeller/runtime_stage/runtime_stage_unittests.cc
@@ -186,7 +186,7 @@
 }
 
 TEST_P(RuntimeStageTest, CanRegisterStage) {
-  if (GetBackend() != PlaygroundBackend::kMetal) {
+  if (GetParam() != PlaygroundBackend::kMetal) {
     GTEST_SKIP_("Skipped: https://github.com/flutter/flutter/issues/105538");
   }
   auto fixture =
@@ -212,7 +212,7 @@
 }
 
 TEST_P(RuntimeStageTest, CanCreatePipelineFromRuntimeStage) {
-  if (GetBackend() != PlaygroundBackend::kMetal) {
+  if (GetParam() != PlaygroundBackend::kMetal) {
     GTEST_SKIP_("Skipped: https://github.com/flutter/flutter/issues/105538");
   }
   auto stage = CreateStageFromFixture("ink_sparkle.frag.iplr");
diff --git a/impeller/typographer/BUILD.gn b/impeller/typographer/BUILD.gn
index 2c0a21f..761b9af 100644
--- a/impeller/typographer/BUILD.gn
+++ b/impeller/typographer/BUILD.gn
@@ -49,6 +49,6 @@
 
   deps = [
     ":typographer",
-    "../playground",
+    "../playground:playground_test",
   ]
 }
diff --git a/impeller/typographer/typographer_unittests.cc b/impeller/typographer/typographer_unittests.cc
index 140d2e3..80b1767 100644
--- a/impeller/typographer/typographer_unittests.cc
+++ b/impeller/typographer/typographer_unittests.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "flutter/testing/testing.h"
-#include "impeller/playground/playground.h"
+#include "impeller/playground/playground_test.h"
 #include "impeller/typographer/backends/skia/text_frame_skia.h"
 #include "impeller/typographer/backends/skia/text_render_context_skia.h"
 #include "third_party/skia/include/core/SkTextBlob.h"
@@ -11,7 +11,7 @@
 namespace impeller {
 namespace testing {
 
-using TypographerTest = Playground;
+using TypographerTest = PlaygroundTest;
 INSTANTIATE_PLAYGROUND_SUITE(TypographerTest);
 
 TEST_P(TypographerTest, CanConvertTextBlob) {