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

Classes

struct  GLFWInitializer
 

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
 
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
 

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
 

Protected Attributes

const PlaygroundSwitches switches_
 

Detailed Description

Definition at line 33 of file playground.h.

Member Typedef Documentation

◆ SinglePassCallback

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

Definition at line 35 of file playground.h.

Constructor & Destructor Documentation

◆ Playground()

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

Definition at line 80 of file playground.cc.

81  : switches_(switches),
82  glfw_initializer_(std::make_unique<GLFWInitializer>()) {}

◆ ~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 487 of file playground.cc.

488  {
489  std::array<DecompressedImage, 6> images;
490  for (size_t i = 0; i < fixture_names.size(); i++) {
491  auto image = DecodeImageRGBA(
493  if (!image.has_value()) {
494  return nullptr;
495  }
496  images[i] = image.value();
497  }
498 
499  auto texture_descriptor = TextureDescriptor{};
500  texture_descriptor.storage_mode = StorageMode::kHostVisible;
501  texture_descriptor.type = TextureType::kTextureCube;
502  texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
503  texture_descriptor.size = images[0].GetSize();
504  texture_descriptor.mip_count = 1u;
505 
506  auto texture = renderer_->GetContext()->GetResourceAllocator()->CreateTexture(
507  texture_descriptor);
508  if (!texture) {
509  VALIDATION_LOG << "Could not allocate texture cube.";
510  return nullptr;
511  }
512  texture->SetLabel("Texture cube");
513 
514  for (size_t i = 0; i < fixture_names.size(); i++) {
515  auto uploaded =
516  texture->SetContents(images[i].GetAllocation()->GetMapping(),
517  images[i].GetAllocation()->GetSize(), i);
518  if (!uploaded) {
519  VALIDATION_LOG << "Could not upload texture to device memory.";
520  return nullptr;
521  }
522  }
523 
524  return texture;
525 }

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 474 of file playground.cc.

476  {
477  auto texture = CreateTextureForMapping(renderer_->GetContext(),
478  OpenAssetAsMapping(fixture_name),
479  enable_mipmapping);
480  if (texture == nullptr) {
481  return nullptr;
482  }
483  texture->SetLabel(fixture_name);
484  return texture;
485 }

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 461 of file playground.cc.

464  {
465  auto image = Playground::DecodeImageRGBA(
466  Playground::LoadFixtureImageCompressed(std::move(mapping)));
467  if (!image.has_value()) {
468  return nullptr;
469  }
470  return CreateTextureForDecompressedImage(context, image.value(),
471  enable_mipmapping);
472 }

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 365 of file playground.cc.

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

References VALIDATION_LOG.

Referenced by CreateTextureCubeForFixture(), and CreateTextureForMapping().

◆ GetContentScale()

Point impeller::Playground::GetContentScale ( ) const

Definition at line 177 of file playground.cc.

177  {
178  return impl_->GetContentScale();
179 }

Referenced by impeller::testing::CanRenderConicalGradientWithDithering(), and impeller::testing::CanRenderSweepGradientWithDithering().

◆ GetContext()

◆ GetCursorPosition()

Point impeller::Playground::GetCursorPosition ( ) const

Definition at line 169 of file playground.cc.

169  {
170  return cursor_position_;
171 }

◆ GetSecondsElapsed()

Scalar impeller::Playground::GetSecondsElapsed ( ) const

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

Definition at line 181 of file playground.cc.

181  {
182  return (fml::TimePoint::Now().ToEpochDelta() - start_time_).ToSecondsF();
183 }

◆ GetWindowSize()

ISize impeller::Playground::GetWindowSize ( ) const

Definition at line 173 of file playground.cc.

173  {
174  return window_size_;
175 }

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 354 of file playground.cc.

355  {
356  auto compressed_image = CompressedImageSkia::Create(std::move(mapping));
357  if (!compressed_image) {
358  VALIDATION_LOG << "Could not create compressed image.";
359  return nullptr;
360  }
361 
362  return compressed_image;
363 }

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

Referenced by CreateTextureCubeForFixture(), and CreateTextureForMapping().

◆ 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 189 of file playground.cc.

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

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(), 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 327 of file playground.cc.

327  {
328  return OpenPlaygroundHere(
329  [context = GetContext(), &pass_callback](RenderTarget& render_target) {
330  auto buffer = context->CreateCommandBuffer();
331  if (!buffer) {
332  return false;
333  }
334  buffer->SetLabel("Playground Command Buffer");
335 
336  auto pass = buffer->CreateRenderPass(render_target);
337  if (!pass) {
338  return false;
339  }
340  pass->SetLabel("Playground Render Pass");
341 
342  if (!pass_callback(*pass)) {
343  return false;
344  }
345 
346  pass->EncodeCommands();
347  if (!buffer->SubmitCommands()) {
348  return false;
349  }
350  return true;
351  });
352 }

References GetContext(), and OpenPlaygroundHere().

◆ SetupContext()

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

Definition at line 114 of file playground.cc.

114  {
115  FML_CHECK(SupportsBackend(backend));
116 
117  impl_ = PlaygroundImpl::Create(backend, switches_);
118  if (!impl_) {
119  FML_LOG(WARNING) << "PlaygroundImpl::Create failed.";
120  return;
121  }
122 
123  context_ = impl_->GetContext();
124 }

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

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

◆ SetupWindow()

void impeller::Playground::SetupWindow ( )

Definition at line 126 of file playground.cc.

126  {
127  if (!context_) {
128  FML_LOG(WARNING) << "Asked to set up a window with no context (call "
129  "SetupContext first).";
130  return;
131  }
132  auto renderer = std::make_unique<Renderer>(context_);
133  if (!renderer->IsValid()) {
134  return;
135  }
136  renderer_ = std::move(renderer);
137 
138  start_time_ = fml::TimePoint::Now().ToEpochDelta();
139 }

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

◆ ShouldKeepRendering()

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

Definition at line 531 of file playground.cc.

531  {
532  return true;
533 }

Referenced by OpenPlaygroundHere().

◆ ShouldOpenNewPlaygrounds()

bool impeller::Playground::ShouldOpenNewPlaygrounds ( )
static

◆ SupportsBackend()

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

Definition at line 90 of file playground.cc.

90  {
91  switch (backend) {
93 #if IMPELLER_ENABLE_METAL
94  return true;
95 #else // IMPELLER_ENABLE_METAL
96  return false;
97 #endif // IMPELLER_ENABLE_METAL
99 #if IMPELLER_ENABLE_OPENGLES
100  return true;
101 #else // IMPELLER_ENABLE_OPENGLES
102  return false;
103 #endif // IMPELLER_ENABLE_OPENGLES
105 #if IMPELLER_ENABLE_VULKAN
106  return true;
107 #else // IMPELLER_ENABLE_VULKAN
108  return false;
109 #endif // IMPELLER_ENABLE_VULKAN
110  }
111  FML_UNREACHABLE();
112 }

References 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 141 of file playground.cc.

141  {
142  if (context_) {
143  context_->Shutdown();
144  }
145  context_.reset();
146  renderer_.reset();
147  impl_.reset();
148 }

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

Member Data Documentation

◆ switches_


The documentation for this class was generated from the following files:
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:384
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::Playground::ShouldKeepRendering
virtual bool ShouldKeepRendering() const
Definition: playground.cc:531
impeller::Renderer::RenderCallback
std::function< bool(RenderTarget &render_target)> RenderCallback
Definition: renderer.h:25
impeller::Playground::DecodeImageRGBA
static std::optional< DecompressedImage > DecodeImageRGBA(const std::shared_ptr< CompressedImage > &compressed)
Definition: playground.cc:365
impeller::Playground::GetWindowSize
ISize GetWindowSize() const
Definition: playground.cc:173
impeller::PlaygroundBackend::kMetal
@ kMetal
impeller::PlaygroundKeyCallback
static void PlaygroundKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
Definition: playground.cc:156
impeller::CompressedImageSkia::Create
static std::shared_ptr< CompressedImage > Create(std::shared_ptr< const fml::Mapping > allocation)
Definition: compressed_image_skia.cc:18
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::gShouldOpenNewPlaygrounds
static std::atomic_bool gShouldOpenNewPlaygrounds
Definition: playground.cc:150
impeller::TSize::Max
constexpr TSize Max(const TSize &o) const
Definition: size.h:78
impeller::Playground::switches_
const PlaygroundSwitches switches_
Definition: playground.h:91
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:24
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:136
ImGui_ImplImpeller_Shutdown
void ImGui_ImplImpeller_Shutdown()
Definition: imgui_impl_impeller.cc:115
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
ImGui_ImplImpeller_RenderDrawData
void ImGui_ImplImpeller_RenderDrawData(ImDrawData *draw_data, impeller::RenderPass &render_pass)
Definition: imgui_impl_impeller.cc:122
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:461
impeller::Playground::LoadFixtureImageCompressed
static std::shared_ptr< CompressedImage > LoadFixtureImageCompressed(std::shared_ptr< fml::Mapping > mapping)
Definition: playground.cc:354
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::Playground::SupportsBackend
static bool SupportsBackend(PlaygroundBackend backend)
Definition: playground.cc:90
impeller::Playground::OpenPlaygroundHere
bool OpenPlaygroundHere(const Renderer::RenderCallback &render_callback)
Definition: playground.cc:189
ImGui_ImplImpeller_Init
bool ImGui_ImplImpeller_Init(const std::shared_ptr< impeller::Context > &context)
Definition: imgui_impl_impeller.cc:51
impeller::Playground::Playground
Playground(PlaygroundSwitches switches)
Definition: playground.cc:80
impeller::Playground::GetContext
std::shared_ptr< Context > GetContext() const
Definition: playground.cc:86
impeller::PlaygroundSwitches::enable_playground
bool enable_playground
Definition: switches.h:16