Flutter Impeller
impeller::Playground Class Referenceabstract

#include <playground.h>

Inheritance diagram for impeller::Playground:
impeller::ComputePlaygroundTest impeller::PlaygroundTest impeller::AiksPlayground impeller::DlPlayground impeller::EntityPlayground impeller::RuntimeStagePlayground impeller::testing::RendererDartTest impeller::testing::GaussianBlurFilterContentsTest

Public Types

using SinglePassCallback = std::function< bool(RenderPass &pass)>
 

Public Member Functions

 Playground (PlaygroundSwitches switches)
 
virtual ~Playground ()
 
void SetupContext (PlaygroundBackend backend)
 
void SetupWindow ()
 
void TeardownWindow ()
 
Point GetCursorPosition () const
 
ISize GetWindowSize () const
 
Point GetContentScale () const
 
Scalar GetSecondsElapsed () const
 Get the amount of time elapsed from the start of the playground's execution. More...
 
std::shared_ptr< ContextGetContext () const
 
std::shared_ptr< ContextMakeContext () const
 
bool OpenPlaygroundHere (const Renderer::RenderCallback &render_callback)
 
bool OpenPlaygroundHere (SinglePassCallback pass_callback)
 
std::shared_ptr< TextureCreateTextureForFixture (const char *fixture_name, bool enable_mipmapping=false) const
 
std::shared_ptr< TextureCreateTextureCubeForFixture (std::array< const char *, 6 > fixture_names) const
 
virtual std::unique_ptr< fml::Mapping > OpenAssetAsMapping (std::string asset_name) const =0
 
virtual std::string GetWindowTitle () const =0
 
fml::Status SetCapabilities (const std::shared_ptr< Capabilities > &capabilities)
 
bool WillRenderSomething () const
 

Static Public Member Functions

static bool ShouldOpenNewPlaygrounds ()
 
static std::shared_ptr< CompressedImageLoadFixtureImageCompressed (std::shared_ptr< fml::Mapping > mapping)
 
static std::optional< DecompressedImageDecodeImageRGBA (const std::shared_ptr< CompressedImage > &compressed)
 
static std::shared_ptr< TextureCreateTextureForMapping (const std::shared_ptr< Context > &context, std::shared_ptr< fml::Mapping > mapping, bool enable_mipmapping=false)
 
static bool SupportsBackend (PlaygroundBackend backend)
 

Protected Member Functions

virtual bool ShouldKeepRendering () const
 
void SetWindowSize (ISize size)
 

Protected Attributes

const PlaygroundSwitches switches_
 

Detailed Description

Definition at line 50 of file playground.h.

Member Typedef Documentation

◆ SinglePassCallback

using impeller::Playground::SinglePassCallback = std::function<bool(RenderPass& pass)>

Definition at line 52 of file playground.h.

Constructor & Destructor Documentation

◆ Playground()

impeller::Playground::Playground ( PlaygroundSwitches  switches)
explicit

◆ ~Playground()

impeller::Playground::~Playground ( )
virtualdefault

Member Function Documentation

◆ CreateTextureCubeForFixture()

std::shared_ptr< Texture > impeller::Playground::CreateTextureCubeForFixture ( std::array< const char *, 6 >  fixture_names) const

Definition at line 462 of file playground.cc.

463  {
464  std::array<DecompressedImage, 6> images;
465  for (size_t i = 0; i < fixture_names.size(); i++) {
466  auto image = DecodeImageRGBA(
468  if (!image.has_value()) {
469  return nullptr;
470  }
471  images[i] = image.value();
472  }
473 
474  auto texture_descriptor = TextureDescriptor{};
475  texture_descriptor.storage_mode = StorageMode::kHostVisible;
476  texture_descriptor.type = TextureType::kTextureCube;
477  texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
478  texture_descriptor.size = images[0].GetSize();
479  texture_descriptor.mip_count = 1u;
480 
481  auto texture = renderer_->GetContext()->GetResourceAllocator()->CreateTexture(
482  texture_descriptor);
483  if (!texture) {
484  VALIDATION_LOG << "Could not allocate texture cube.";
485  return nullptr;
486  }
487  texture->SetLabel("Texture cube");
488 
489  for (size_t i = 0; i < fixture_names.size(); i++) {
490  auto uploaded =
491  texture->SetContents(images[i].GetAllocation()->GetMapping(),
492  images[i].GetAllocation()->GetSize(), i);
493  if (!uploaded) {
494  VALIDATION_LOG << "Could not upload texture to device memory.";
495  return nullptr;
496  }
497  }
498 
499  return texture;
500 }

References DecodeImageRGBA(), impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::kTextureCube, LoadFixtureImageCompressed(), OpenAssetAsMapping(), impeller::TextureDescriptor::storage_mode, and VALIDATION_LOG.

◆ CreateTextureForFixture()

std::shared_ptr< Texture > impeller::Playground::CreateTextureForFixture ( const char *  fixture_name,
bool  enable_mipmapping = false 
) const

Definition at line 449 of file playground.cc.

451  {
452  auto texture = CreateTextureForMapping(renderer_->GetContext(),
453  OpenAssetAsMapping(fixture_name),
454  enable_mipmapping);
455  if (texture == nullptr) {
456  return nullptr;
457  }
458  texture->SetLabel(fixture_name);
459  return texture;
460 }

References CreateTextureForMapping(), and OpenAssetAsMapping().

◆ CreateTextureForMapping()

std::shared_ptr< Texture > impeller::Playground::CreateTextureForMapping ( const std::shared_ptr< Context > &  context,
std::shared_ptr< fml::Mapping >  mapping,
bool  enable_mipmapping = false 
)
static

Definition at line 436 of file playground.cc.

439  {
440  auto image = Playground::DecodeImageRGBA(
441  Playground::LoadFixtureImageCompressed(std::move(mapping)));
442  if (!image.has_value()) {
443  return nullptr;
444  }
445  return CreateTextureForDecompressedImage(context, image.value(),
446  enable_mipmapping);
447 }

References impeller::CreateTextureForDecompressedImage(), DecodeImageRGBA(), and LoadFixtureImageCompressed().

Referenced by impeller::GoldenPlaygroundTest::CreateTextureForFixture(), and CreateTextureForFixture().

◆ DecodeImageRGBA()

std::optional< DecompressedImage > impeller::Playground::DecodeImageRGBA ( const std::shared_ptr< CompressedImage > &  compressed)
static

Definition at line 374 of file playground.cc.

375  {
376  if (compressed == nullptr) {
377  return std::nullopt;
378  }
379  // The decoded image is immediately converted into RGBA as that format is
380  // known to be supported everywhere. For image sources that don't need 32
381  // bit pixel strides, this is overkill. Since this is a test fixture we
382  // aren't necessarily trying to eke out memory savings here and instead
383  // favor simplicity.
384  auto image = compressed->Decode().ConvertToRGBA();
385  if (!image.IsValid()) {
386  VALIDATION_LOG << "Could not decode image.";
387  return std::nullopt;
388  }
389 
390  return image;
391 }

References VALIDATION_LOG.

Referenced by CreateTextureCubeForFixture(), and CreateTextureForMapping().

◆ GetContentScale()

Point impeller::Playground::GetContentScale ( ) const

◆ GetContext()

◆ GetCursorPosition()

Point impeller::Playground::GetCursorPosition ( ) const

Definition at line 178 of file playground.cc.

178  {
179  return cursor_position_;
180 }

◆ GetSecondsElapsed()

Scalar impeller::Playground::GetSecondsElapsed ( ) const

Get the amount of time elapsed from the start of the playground's execution.

Definition at line 190 of file playground.cc.

190  {
191  return (fml::TimePoint::Now().ToEpochDelta() - start_time_).ToSecondsF();
192 }

◆ GetWindowSize()

ISize impeller::Playground::GetWindowSize ( ) const

Definition at line 182 of file playground.cc.

182  {
183  return window_size_;
184 }

Referenced by OpenPlaygroundHere().

◆ GetWindowTitle()

virtual std::string impeller::Playground::GetWindowTitle ( ) const
pure virtual

◆ LoadFixtureImageCompressed()

std::shared_ptr< CompressedImage > impeller::Playground::LoadFixtureImageCompressed ( std::shared_ptr< fml::Mapping >  mapping)
static

Definition at line 363 of file playground.cc.

364  {
365  auto compressed_image = CompressedImageSkia::Create(std::move(mapping));
366  if (!compressed_image) {
367  VALIDATION_LOG << "Could not create compressed image.";
368  return nullptr;
369  }
370 
371  return compressed_image;
372 }

References impeller::CompressedImageSkia::Create(), and VALIDATION_LOG.

Referenced by CreateTextureCubeForFixture(), and CreateTextureForMapping().

◆ MakeContext()

std::shared_ptr< Context > impeller::Playground::MakeContext ( ) const

Definition at line 93 of file playground.cc.

93  {
94  // Playgrounds are already making a context for each test, so we can just
95  // return the `context_`.
96  return context_;
97 }

◆ OpenAssetAsMapping()

virtual std::unique_ptr<fml::Mapping> impeller::Playground::OpenAssetAsMapping ( std::string  asset_name) const
pure virtual

◆ OpenPlaygroundHere() [1/2]

bool impeller::Playground::OpenPlaygroundHere ( const Renderer::RenderCallback render_callback)

Definition at line 198 of file playground.cc.

199  {
201  return true;
202  }
203 
204  if (!render_callback) {
205  return true;
206  }
207 
208  if (!renderer_ || !renderer_->IsValid()) {
209  return false;
210  }
211 
212  IMGUI_CHECKVERSION();
213  ImGui::CreateContext();
214  fml::ScopedCleanupClosure destroy_imgui_context(
215  []() { ImGui::DestroyContext(); });
216  ImGui::StyleColorsDark();
217 
218  auto& io = ImGui::GetIO();
219  io.IniFilename = nullptr;
220  io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
221  io.ConfigWindowsResizeFromEdges = true;
222 
223  auto window = reinterpret_cast<GLFWwindow*>(impl_->GetWindowHandle());
224  if (!window) {
225  return false;
226  }
227  ::glfwSetWindowTitle(window, GetWindowTitle().c_str());
228  ::glfwSetWindowUserPointer(window, this);
229  ::glfwSetWindowSizeCallback(
230  window, [](GLFWwindow* window, int width, int height) -> void {
231  auto playground =
232  reinterpret_cast<Playground*>(::glfwGetWindowUserPointer(window));
233  if (!playground) {
234  return;
235  }
236  playground->SetWindowSize(ISize{width, height}.Max({}));
237  });
238  ::glfwSetKeyCallback(window, &PlaygroundKeyCallback);
239  ::glfwSetCursorPosCallback(window, [](GLFWwindow* window, double x,
240  double y) {
241  reinterpret_cast<Playground*>(::glfwGetWindowUserPointer(window))
242  ->SetCursorPosition({static_cast<Scalar>(x), static_cast<Scalar>(y)});
243  });
244 
245  ImGui_ImplGlfw_InitForOther(window, true);
246  fml::ScopedCleanupClosure shutdown_imgui([]() { ImGui_ImplGlfw_Shutdown(); });
247 
248  ImGui_ImplImpeller_Init(renderer_->GetContext());
249  fml::ScopedCleanupClosure shutdown_imgui_impeller(
250  []() { ImGui_ImplImpeller_Shutdown(); });
251 
252  ImGui::SetNextWindowPos({10, 10});
253 
254  ::glfwSetWindowSize(window, GetWindowSize().width, GetWindowSize().height);
255  ::glfwSetWindowPos(window, 200, 100);
256  ::glfwShowWindow(window);
257 
258  while (true) {
259 #if FML_OS_MACOSX
260  fml::ScopedNSAutoreleasePool pool;
261 #endif
262  ::glfwPollEvents();
263 
264  if (::glfwWindowShouldClose(window)) {
265  return true;
266  }
267 
268  ImGui_ImplGlfw_NewFrame();
269 
270  Renderer::RenderCallback wrapped_callback =
271  [render_callback,
272  &renderer = renderer_](RenderTarget& render_target) -> bool {
273  ImGui::NewFrame();
274  ImGui::DockSpaceOverViewport(ImGui::GetMainViewport(),
275  ImGuiDockNodeFlags_PassthruCentralNode);
276  bool result = render_callback(render_target);
277  ImGui::Render();
278 
279  // Render ImGui overlay.
280  {
281  auto buffer = renderer->GetContext()->CreateCommandBuffer();
282  if (!buffer) {
283  return false;
284  }
285  buffer->SetLabel("ImGui Command Buffer");
286 
287  if (render_target.GetColorAttachments().empty()) {
288  return false;
289  }
290 
291  auto color0 = render_target.GetColorAttachments().find(0)->second;
292  color0.load_action = LoadAction::kLoad;
293  if (color0.resolve_texture) {
294  color0.texture = color0.resolve_texture;
295  color0.resolve_texture = nullptr;
296  color0.store_action = StoreAction::kStore;
297  }
298  render_target.SetColorAttachment(color0, 0);
299 
300  render_target.SetStencilAttachment(std::nullopt);
301  render_target.SetDepthAttachment(std::nullopt);
302 
303  auto pass = buffer->CreateRenderPass(render_target);
304  if (!pass) {
305  return false;
306  }
307  pass->SetLabel("ImGui Render Pass");
308 
309  ImGui_ImplImpeller_RenderDrawData(ImGui::GetDrawData(), *pass);
310 
311  pass->EncodeCommands();
312  if (!renderer->GetContext()->GetCommandQueue()->Submit({buffer}).ok()) {
313  return false;
314  }
315  }
316 
317  return result;
318  };
319 
320  if (!renderer_->Render(impl_->AcquireSurfaceFrame(renderer_->GetContext()),
321  wrapped_callback)) {
322  VALIDATION_LOG << "Could not render into the surface.";
323  return false;
324  }
325 
326  if (!ShouldKeepRendering()) {
327  break;
328  }
329  }
330 
331  ::glfwHideWindow(window);
332 
333  return true;
334 }

References impeller::PlaygroundSwitches::enable_playground, GetWindowSize(), GetWindowTitle(), ImGui_ImplImpeller_Init(), ImGui_ImplImpeller_RenderDrawData(), ImGui_ImplImpeller_Shutdown(), impeller::kLoad, impeller::kStore, impeller::TSize< T >::Max(), impeller::PlaygroundKeyCallback(), SetWindowSize(), ShouldKeepRendering(), switches_, and VALIDATION_LOG.

Referenced by impeller::DlPlayground::OpenPlaygroundHere(), impeller::EntityPlayground::OpenPlaygroundHere(), impeller::AiksPlayground::OpenPlaygroundHere(), and OpenPlaygroundHere().

◆ OpenPlaygroundHere() [2/2]

bool impeller::Playground::OpenPlaygroundHere ( SinglePassCallback  pass_callback)

Definition at line 336 of file playground.cc.

336  {
337  return OpenPlaygroundHere(
338  [context = GetContext(), &pass_callback](RenderTarget& render_target) {
339  auto buffer = context->CreateCommandBuffer();
340  if (!buffer) {
341  return false;
342  }
343  buffer->SetLabel("Playground Command Buffer");
344 
345  auto pass = buffer->CreateRenderPass(render_target);
346  if (!pass) {
347  return false;
348  }
349  pass->SetLabel("Playground Render Pass");
350 
351  if (!pass_callback(*pass)) {
352  return false;
353  }
354 
355  pass->EncodeCommands();
356  if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
357  return false;
358  }
359  return true;
360  });
361 }

References GetContext(), and OpenPlaygroundHere().

◆ SetCapabilities()

fml::Status impeller::Playground::SetCapabilities ( const std::shared_ptr< Capabilities > &  capabilities)

Definition at line 510 of file playground.cc.

511  {
512  return impl_->SetCapabilities(capabilities);
513 }

◆ SetupContext()

void impeller::Playground::SetupContext ( PlaygroundBackend  backend)

Definition at line 123 of file playground.cc.

123  {
124  FML_CHECK(SupportsBackend(backend));
125 
126  impl_ = PlaygroundImpl::Create(backend, switches_);
127  if (!impl_) {
128  FML_LOG(WARNING) << "PlaygroundImpl::Create failed.";
129  return;
130  }
131 
132  context_ = impl_->GetContext();
133 }

References impeller::PlaygroundImpl::Create(), SupportsBackend(), and switches_.

Referenced by impeller::ComputePlaygroundTest::SetUp(), and impeller::PlaygroundTest::SetUp().

◆ SetupWindow()

void impeller::Playground::SetupWindow ( )

Definition at line 135 of file playground.cc.

135  {
136  if (!context_) {
137  FML_LOG(WARNING) << "Asked to set up a window with no context (call "
138  "SetupContext first).";
139  return;
140  }
141  auto renderer = std::make_unique<Renderer>(context_);
142  if (!renderer->IsValid()) {
143  return;
144  }
145  renderer_ = std::move(renderer);
146 
147  start_time_ = fml::TimePoint::Now().ToEpochDelta();
148 }

Referenced by impeller::ComputePlaygroundTest::SetUp(), and impeller::PlaygroundTest::SetUp().

◆ SetWindowSize()

void impeller::Playground::SetWindowSize ( ISize  size)
protected

Definition at line 502 of file playground.cc.

502  {
503  window_size_ = size;
504 }

Referenced by OpenPlaygroundHere().

◆ ShouldKeepRendering()

bool impeller::Playground::ShouldKeepRendering ( ) const
protectedvirtual

Definition at line 506 of file playground.cc.

506  {
507  return true;
508 }

Referenced by OpenPlaygroundHere().

◆ ShouldOpenNewPlaygrounds()

bool impeller::Playground::ShouldOpenNewPlaygrounds ( )
static

◆ SupportsBackend()

bool impeller::Playground::SupportsBackend ( PlaygroundBackend  backend)
static

Definition at line 99 of file playground.cc.

99  {
100  switch (backend) {
102 #if IMPELLER_ENABLE_METAL
103  return true;
104 #else // IMPELLER_ENABLE_METAL
105  return false;
106 #endif // IMPELLER_ENABLE_METAL
108 #if IMPELLER_ENABLE_OPENGLES
109  return true;
110 #else // IMPELLER_ENABLE_OPENGLES
111  return false;
112 #endif // IMPELLER_ENABLE_OPENGLES
114 #if IMPELLER_ENABLE_VULKAN
116 #else // IMPELLER_ENABLE_VULKAN
117  return false;
118 #endif // IMPELLER_ENABLE_VULKAN
119  }
120  FML_UNREACHABLE();
121 }

References impeller::PlaygroundImplVK::IsVulkanDriverPresent(), impeller::kMetal, impeller::kOpenGLES, and impeller::kVulkan.

Referenced by impeller::ComputePlaygroundTest::SetUp(), impeller::PlaygroundTest::SetUp(), and SetupContext().

◆ TeardownWindow()

void impeller::Playground::TeardownWindow ( )

Definition at line 150 of file playground.cc.

150  {
151  if (context_) {
152  context_->Shutdown();
153  }
154  context_.reset();
155  renderer_.reset();
156  impl_.reset();
157 }

Referenced by impeller::ComputePlaygroundTest::TearDown(), and impeller::PlaygroundTest::TearDown().

◆ WillRenderSomething()

bool impeller::Playground::WillRenderSomething ( ) const

TODO(https://github.com/flutter/flutter/issues/139950): Remove this. Returns true if OpenPlaygroundHere will actually render anything.

Definition at line 515 of file playground.cc.

515  {
517 }

References impeller::PlaygroundSwitches::enable_playground, and switches_.

Member Data Documentation

◆ switches_


The documentation for this class was generated from the following files:
impeller::PlaygroundImplVK::IsVulkanDriverPresent
static bool IsVulkanDriverPresent()
Definition: playground_impl_vk.cc:216
impeller::LoadAction::kLoad
@ kLoad
impeller::PlaygroundBackend::kVulkan
@ kVulkan
impeller::CreateTextureForDecompressedImage
static std::shared_ptr< Texture > CreateTextureForDecompressedImage(const std::shared_ptr< Context > &context, DecompressedImage &decompressed_image, bool enable_mipmapping)
Definition: playground.cc:393
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Playground::ShouldKeepRendering
virtual bool ShouldKeepRendering() const
Definition: playground.cc:506
impeller::Renderer::RenderCallback
std::function< bool(RenderTarget &render_target)> RenderCallback
Definition: renderer.h:23
impeller::Playground::DecodeImageRGBA
static std::optional< DecompressedImage > DecodeImageRGBA(const std::shared_ptr< CompressedImage > &compressed)
Definition: playground.cc:374
impeller::Playground::GetWindowSize
ISize GetWindowSize() const
Definition: playground.cc:182
impeller::PlaygroundBackend::kMetal
@ kMetal
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::PlaygroundKeyCallback
static void PlaygroundKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
Definition: playground.cc:165
impeller::CompressedImageSkia::Create
static std::shared_ptr< CompressedImage > Create(std::shared_ptr< const fml::Mapping > allocation)
Definition: compressed_image_skia.cc:18
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::PlaygroundSwitches::use_swiftshader
bool use_swiftshader
Definition: switches.h:28
impeller::gShouldOpenNewPlaygrounds
static std::atomic_bool gShouldOpenNewPlaygrounds
Definition: playground.cc:159
impeller::TSize::Max
constexpr TSize Max(const TSize &o) const
Definition: size.h:81
impeller::InitializeGLFWOnce
static void InitializeGLFWOnce()
Definition: playground.cc:56
impeller::Playground::switches_
const PlaygroundSwitches switches_
Definition: playground.h:117
impeller::TextureType::kTextureCube
@ kTextureCube
impeller::StoreAction::kStore
@ kStore
impeller::PlaygroundImpl::Create
static std::unique_ptr< PlaygroundImpl > Create(PlaygroundBackend backend, PlaygroundSwitches switches)
Definition: playground_impl.cc:25
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
ImGui_ImplImpeller_Shutdown
void ImGui_ImplImpeller_Shutdown()
Definition: imgui_impl_impeller.cc:119
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
ImGui_ImplImpeller_RenderDrawData
void ImGui_ImplImpeller_RenderDrawData(ImDrawData *draw_data, impeller::RenderPass &render_pass)
Definition: imgui_impl_impeller.cc:126
impeller::PlaygroundBackend::kOpenGLES
@ kOpenGLES
impeller::Playground::CreateTextureForMapping
static std::shared_ptr< Texture > CreateTextureForMapping(const std::shared_ptr< Context > &context, std::shared_ptr< fml::Mapping > mapping, bool enable_mipmapping=false)
Definition: playground.cc:436
impeller::Playground::LoadFixtureImageCompressed
static std::shared_ptr< CompressedImage > LoadFixtureImageCompressed(std::shared_ptr< fml::Mapping > mapping)
Definition: playground.cc:363
impeller::Playground::GetWindowTitle
virtual std::string GetWindowTitle() const =0
impeller::Playground::OpenAssetAsMapping
virtual std::unique_ptr< fml::Mapping > OpenAssetAsMapping(std::string asset_name) const =0
impeller::SetupSwiftshaderOnce
void SetupSwiftshaderOnce(bool use_swiftshader)
Find and setup the installable client driver for a locally built SwiftShader at known paths....
Definition: swiftshader_utilities.cc:54
impeller::Playground::SupportsBackend
static bool SupportsBackend(PlaygroundBackend backend)
Definition: playground.cc:99
impeller::Playground::OpenPlaygroundHere
bool OpenPlaygroundHere(const Renderer::RenderCallback &render_callback)
Definition: playground.cc:198
ImGui_ImplImpeller_Init
bool ImGui_ImplImpeller_Init(const std::shared_ptr< impeller::Context > &context)
Definition: imgui_impl_impeller.cc:56
impeller::Playground::Playground
Playground(PlaygroundSwitches switches)
Definition: playground.cc:82
impeller::Playground::GetContext
std::shared_ptr< Context > GetContext() const
Definition: playground.cc:89
impeller::PlaygroundSwitches::enable_playground
bool enable_playground
Definition: switches.h:17