Flutter Impeller
playground.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <array>
6 #include <memory>
7 #include <optional>
8 #include <sstream>
9 
10 #include "fml/closure.h"
11 #include "fml/time/time_point.h"
17 
18 #define GLFW_INCLUDE_NONE
19 #include "third_party/glfw/include/GLFW/glfw3.h"
20 
21 #include "flutter/fml/paths.h"
24 #include "impeller/core/formats.h"
32 #include "third_party/imgui/backends/imgui_impl_glfw.h"
33 #include "third_party/imgui/imgui.h"
34 
35 #if FML_OS_MACOSX
36 #include "fml/platform/darwin/scoped_nsautorelease_pool.h"
37 #endif // FML_OS_MACOSX
38 
39 #if IMPELLER_ENABLE_VULKAN
41 #endif // IMPELLER_ENABLE_VULKAN
42 
43 namespace impeller {
44 
46  switch (backend) {
48  return "Metal";
50  return "OpenGLES";
52  return "Vulkan";
53  }
54  FML_UNREACHABLE();
55 }
56 
57 static void InitializeGLFWOnce() {
58  // This guard is a hack to work around a problem where glfwCreateWindow
59  // hangs when opening a second window after GLFW has been reinitialized (for
60  // example, when flipping through multiple playground tests).
61  //
62  // Explanation:
63  // * glfwCreateWindow calls [NSApp run], which begins running the event
64  // loop on the current thread.
65  // * GLFW then immediately stops the loop when
66  // applicationDidFinishLaunching is fired.
67  // * applicationDidFinishLaunching is only ever fired once during the
68  // application's lifetime, so subsequent calls to [NSApp run] will always
69  // hang with this setup.
70  // * glfwInit resets the flag that guards against [NSApp run] being
71  // called a second time, which causes the subsequent `glfwCreateWindow`
72  // to hang indefinitely in the event loop, because
73  // applicationDidFinishLaunching is never fired.
74  static std::once_flag sOnceInitializer;
75  std::call_once(sOnceInitializer, []() {
76  ::glfwSetErrorCallback([](int code, const char* description) {
77  FML_LOG(ERROR) << "GLFW Error '" << description << "' (" << code << ").";
78  });
79  FML_CHECK(::glfwInit() == GLFW_TRUE);
80  });
81 }
82 
83 Playground::Playground(PlaygroundSwitches switches) : switches_(switches) {
86 }
87 
88 Playground::~Playground() = default;
89 
90 std::shared_ptr<Context> Playground::GetContext() const {
91  return context_;
92 }
93 
94 std::shared_ptr<Context> Playground::MakeContext() const {
95  // Playgrounds are already making a context for each test, so we can just
96  // return the `context_`.
97  return context_;
98 }
99 
101  switch (backend) {
103 #if IMPELLER_ENABLE_METAL
104  return true;
105 #else // IMPELLER_ENABLE_METAL
106  return false;
107 #endif // IMPELLER_ENABLE_METAL
109 #if IMPELLER_ENABLE_OPENGLES
110  return true;
111 #else // IMPELLER_ENABLE_OPENGLES
112  return false;
113 #endif // IMPELLER_ENABLE_OPENGLES
115 #if IMPELLER_ENABLE_VULKAN
117 #else // IMPELLER_ENABLE_VULKAN
118  return false;
119 #endif // IMPELLER_ENABLE_VULKAN
120  }
121  FML_UNREACHABLE();
122 }
123 
125  const PlaygroundSwitches& switches) {
126  FML_CHECK(SupportsBackend(backend));
127 
128  impl_ = PlaygroundImpl::Create(backend, switches);
129  if (!impl_) {
130  FML_LOG(WARNING) << "PlaygroundImpl::Create failed.";
131  return;
132  }
133 
134  context_ = impl_->GetContext();
135 }
136 
138  if (!context_) {
139  FML_LOG(WARNING) << "Asked to set up a window with no context (call "
140  "SetupContext first).";
141  return;
142  }
143  start_time_ = fml::TimePoint::Now().ToEpochDelta();
144 }
145 
148 }
149 
151  if (context_) {
152  context_->Shutdown();
153  }
154  context_.reset();
155  impl_.reset();
156 }
157 
158 static std::atomic_bool gShouldOpenNewPlaygrounds = true;
159 
162 }
163 
164 static void PlaygroundKeyCallback(GLFWwindow* window,
165  int key,
166  int scancode,
167  int action,
168  int mods) {
169  if ((key == GLFW_KEY_ESCAPE) && action == GLFW_RELEASE) {
170  if (mods & (GLFW_MOD_CONTROL | GLFW_MOD_SUPER | GLFW_MOD_SHIFT)) {
172  }
173  ::glfwSetWindowShouldClose(window, GLFW_TRUE);
174  }
175 }
176 
178  return cursor_position_;
179 }
180 
182  return window_size_;
183 }
184 
186  return impl_->GetContentScale();
187 }
188 
190  return (fml::TimePoint::Now().ToEpochDelta() - start_time_).ToSecondsF();
191 }
192 
193 void Playground::SetCursorPosition(Point pos) {
194  cursor_position_ = pos;
195 }
196 
198  const Playground::RenderCallback& render_callback) {
200  return true;
201  }
202 
203  if (!render_callback) {
204  return true;
205  }
206 
207  IMGUI_CHECKVERSION();
208  ImGui::CreateContext();
209  fml::ScopedCleanupClosure destroy_imgui_context(
210  []() { ImGui::DestroyContext(); });
211  ImGui::StyleColorsDark();
212 
213  auto& io = ImGui::GetIO();
214  io.IniFilename = nullptr;
215  io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
216  io.ConfigWindowsResizeFromEdges = true;
217 
218  auto window = reinterpret_cast<GLFWwindow*>(impl_->GetWindowHandle());
219  if (!window) {
220  return false;
221  }
222  ::glfwSetWindowTitle(window, GetWindowTitle().c_str());
223  ::glfwSetWindowUserPointer(window, this);
224  ::glfwSetWindowSizeCallback(
225  window, [](GLFWwindow* window, int width, int height) -> void {
226  auto playground =
227  reinterpret_cast<Playground*>(::glfwGetWindowUserPointer(window));
228  if (!playground) {
229  return;
230  }
231  playground->SetWindowSize(ISize{width, height}.Max({}));
232  });
233  ::glfwSetKeyCallback(window, &PlaygroundKeyCallback);
234  ::glfwSetCursorPosCallback(window, [](GLFWwindow* window, double x,
235  double y) {
236  reinterpret_cast<Playground*>(::glfwGetWindowUserPointer(window))
237  ->SetCursorPosition({static_cast<Scalar>(x), static_cast<Scalar>(y)});
238  });
239 
240  ImGui_ImplGlfw_InitForOther(window, true);
241  fml::ScopedCleanupClosure shutdown_imgui([]() { ImGui_ImplGlfw_Shutdown(); });
242 
243  ImGui_ImplImpeller_Init(context_);
244  fml::ScopedCleanupClosure shutdown_imgui_impeller(
245  []() { ImGui_ImplImpeller_Shutdown(); });
246 
247  ImGui::SetNextWindowPos({10, 10});
248 
249  ::glfwSetWindowSize(window, GetWindowSize().width, GetWindowSize().height);
250  ::glfwSetWindowPos(window, 200, 100);
251  ::glfwShowWindow(window);
252 
253  while (true) {
254 #if FML_OS_MACOSX
255  fml::ScopedNSAutoreleasePool pool;
256 #endif
257  ::glfwPollEvents();
258 
259  if (::glfwWindowShouldClose(window)) {
260  return true;
261  }
262 
263  ImGui_ImplGlfw_NewFrame();
264 
265  auto surface = impl_->AcquireSurfaceFrame(context_);
266  RenderTarget render_target = surface->GetRenderTarget();
267 
268  ImGui::NewFrame();
269  ImGui::DockSpaceOverViewport(ImGui::GetMainViewport(),
270  ImGuiDockNodeFlags_PassthruCentralNode);
271  bool result = render_callback(render_target);
272  ImGui::Render();
273 
274  // Render ImGui overlay.
275  {
276  auto buffer = context_->CreateCommandBuffer();
277  if (!buffer) {
278  VALIDATION_LOG << "Could not create command buffer.";
279  return false;
280  }
281  buffer->SetLabel("ImGui Command Buffer");
282 
283  if (render_target.GetColorAttachments().empty()) {
284  VALIDATION_LOG << "render target attachments are empty.";
285  return false;
286  }
287 
288  auto color0 = render_target.GetColorAttachments().find(0)->second;
289  color0.load_action = LoadAction::kLoad;
290  if (color0.resolve_texture) {
291  color0.texture = color0.resolve_texture;
292  color0.resolve_texture = nullptr;
293  color0.store_action = StoreAction::kStore;
294  }
295  render_target.SetColorAttachment(color0, 0);
296 
297  render_target.SetStencilAttachment(std::nullopt);
298  render_target.SetDepthAttachment(std::nullopt);
299 
300  auto pass = buffer->CreateRenderPass(render_target);
301  if (!pass) {
302  VALIDATION_LOG << "Could not create render pass.";
303  return false;
304  }
305  pass->SetLabel("ImGui Render Pass");
306 
307  ImGui_ImplImpeller_RenderDrawData(ImGui::GetDrawData(), *pass);
308 
309  pass->EncodeCommands();
310 
311  if (!context_->GetCommandQueue()->Submit({buffer}).ok()) {
312  return false;
313  }
314  }
315 
316  if (!result || !surface->Present()) {
317  return false;
318  }
319 
320  if (!ShouldKeepRendering()) {
321  break;
322  }
323  }
324 
325  ::glfwHideWindow(window);
326 
327  return true;
328 }
329 
331  return OpenPlaygroundHere(
332  [context = GetContext(), &pass_callback](RenderTarget& render_target) {
333  auto buffer = context->CreateCommandBuffer();
334  if (!buffer) {
335  return false;
336  }
337  buffer->SetLabel("Playground Command Buffer");
338 
339  auto pass = buffer->CreateRenderPass(render_target);
340  if (!pass) {
341  return false;
342  }
343  pass->SetLabel("Playground Render Pass");
344 
345  if (!pass_callback(*pass)) {
346  return false;
347  }
348 
349  pass->EncodeCommands();
350  if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
351  return false;
352  }
353  return true;
354  });
355 }
356 
357 std::shared_ptr<CompressedImage> Playground::LoadFixtureImageCompressed(
358  std::shared_ptr<fml::Mapping> mapping) {
359  auto compressed_image = CompressedImageSkia::Create(std::move(mapping));
360  if (!compressed_image) {
361  VALIDATION_LOG << "Could not create compressed image.";
362  return nullptr;
363  }
364 
365  return compressed_image;
366 }
367 
368 std::optional<DecompressedImage> Playground::DecodeImageRGBA(
369  const std::shared_ptr<CompressedImage>& compressed) {
370  if (compressed == nullptr) {
371  return std::nullopt;
372  }
373  // The decoded image is immediately converted into RGBA as that format is
374  // known to be supported everywhere. For image sources that don't need 32
375  // bit pixel strides, this is overkill. Since this is a test fixture we
376  // aren't necessarily trying to eke out memory savings here and instead
377  // favor simplicity.
378  auto image = compressed->Decode().ConvertToRGBA();
379  if (!image.IsValid()) {
380  VALIDATION_LOG << "Could not decode image.";
381  return std::nullopt;
382  }
383 
384  return image;
385 }
386 
387 static std::shared_ptr<Texture> CreateTextureForDecompressedImage(
388  const std::shared_ptr<Context>& context,
389  DecompressedImage& decompressed_image,
390  bool enable_mipmapping) {
391  auto texture_descriptor = TextureDescriptor{};
392  texture_descriptor.storage_mode = StorageMode::kHostVisible;
393  texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
394  texture_descriptor.size = decompressed_image.GetSize();
395  texture_descriptor.mip_count =
396  enable_mipmapping ? decompressed_image.GetSize().MipCount() : 1u;
397 
398  auto texture =
399  context->GetResourceAllocator()->CreateTexture(texture_descriptor);
400  if (!texture) {
401  VALIDATION_LOG << "Could not allocate texture for fixture.";
402  return nullptr;
403  }
404 
405  auto command_buffer = context->CreateCommandBuffer();
406  if (!command_buffer) {
407  FML_DLOG(ERROR) << "Could not create command buffer for mipmap generation.";
408  return nullptr;
409  }
410  command_buffer->SetLabel("Mipmap Command Buffer");
411 
412  auto blit_pass = command_buffer->CreateBlitPass();
414  context->GetResourceAllocator()->CreateBufferWithCopy(
415  *decompressed_image.GetAllocation()));
416  blit_pass->AddCopy(buffer_view, texture);
417  if (enable_mipmapping) {
418  blit_pass->SetLabel("Mipmap Blit Pass");
419  blit_pass->GenerateMipmap(texture);
420  }
421  blit_pass->EncodeCommands(context->GetResourceAllocator());
422  if (!context->GetCommandQueue()->Submit({command_buffer}).ok()) {
423  FML_DLOG(ERROR) << "Failed to submit blit pass command buffer.";
424  return nullptr;
425  }
426  return texture;
427 }
428 
429 std::shared_ptr<Texture> Playground::CreateTextureForMapping(
430  const std::shared_ptr<Context>& context,
431  std::shared_ptr<fml::Mapping> mapping,
432  bool enable_mipmapping) {
433  auto image = Playground::DecodeImageRGBA(
434  Playground::LoadFixtureImageCompressed(std::move(mapping)));
435  if (!image.has_value()) {
436  return nullptr;
437  }
438  return CreateTextureForDecompressedImage(context, image.value(),
439  enable_mipmapping);
440 }
441 
442 std::shared_ptr<Texture> Playground::CreateTextureForFixture(
443  const char* fixture_name,
444  bool enable_mipmapping) const {
445  auto texture = CreateTextureForMapping(
446  context_, OpenAssetAsMapping(fixture_name), enable_mipmapping);
447  if (texture == nullptr) {
448  return nullptr;
449  }
450  texture->SetLabel(fixture_name);
451  return texture;
452 }
453 
455  std::array<const char*, 6> fixture_names) const {
456  std::array<DecompressedImage, 6> images;
457  for (size_t i = 0; i < fixture_names.size(); i++) {
458  auto image = DecodeImageRGBA(
460  if (!image.has_value()) {
461  return nullptr;
462  }
463  images[i] = image.value();
464  }
465 
466  auto texture_descriptor = TextureDescriptor{};
467  texture_descriptor.storage_mode = StorageMode::kHostVisible;
468  texture_descriptor.type = TextureType::kTextureCube;
469  texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
470  texture_descriptor.size = images[0].GetSize();
471  texture_descriptor.mip_count = 1u;
472 
473  auto texture =
474  context_->GetResourceAllocator()->CreateTexture(texture_descriptor);
475  if (!texture) {
476  VALIDATION_LOG << "Could not allocate texture cube.";
477  return nullptr;
478  }
479  texture->SetLabel("Texture cube");
480 
481  auto cmd_buffer = context_->CreateCommandBuffer();
482  auto blit_pass = cmd_buffer->CreateBlitPass();
483  for (size_t i = 0; i < fixture_names.size(); i++) {
484  auto device_buffer = context_->GetResourceAllocator()->CreateBufferWithCopy(
485  *images[i].GetAllocation());
486  blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer), texture, {},
487  "", /*slice=*/i);
488  }
489 
490  if (!blit_pass->EncodeCommands(context_->GetResourceAllocator()) ||
491  !context_->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok()) {
492  VALIDATION_LOG << "Could not upload texture to device memory.";
493  return nullptr;
494  }
495 
496  return texture;
497 }
498 
500  window_size_ = size;
501 }
502 
504  return true;
505 }
506 
508  const std::shared_ptr<Capabilities>& capabilities) {
509  return impl_->SetCapabilities(capabilities);
510 }
511 
514 }
515 
517  const {
518  return impl_->CreateGLProcAddressResolver();
519 }
520 
521 } // namespace impeller
impeller::DecompressedImage
Definition: decompressed_image.h:15
impeller::DeviceBuffer::AsBufferView
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
Definition: device_buffer.cc:18
impeller::Playground::ShouldOpenNewPlaygrounds
static bool ShouldOpenNewPlaygrounds()
Definition: playground.cc:160
impeller::PlaygroundImplVK::IsVulkanDriverPresent
static bool IsVulkanDriverPresent()
Definition: playground_impl_vk.cc:220
impeller::Playground::CreateTextureCubeForFixture
std::shared_ptr< Texture > CreateTextureCubeForFixture(std::array< const char *, 6 > fixture_names) const
Definition: playground.cc:454
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:387
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Playground::WillRenderSomething
bool WillRenderSomething() const
Returns true if OpenPlaygroundHere will actually render anything.
Definition: playground.cc:512
impeller::Playground::ShouldKeepRendering
virtual bool ShouldKeepRendering() const
Definition: playground.cc:503
impeller::Playground::DecodeImageRGBA
static std::optional< DecompressedImage > DecodeImageRGBA(const std::shared_ptr< CompressedImage > &compressed)
Definition: playground.cc:368
impeller::Playground::GetSecondsElapsed
Scalar GetSecondsElapsed() const
Get the amount of time elapsed from the start of the playground's execution.
Definition: playground.cc:189
impeller::Playground::GetWindowSize
ISize GetWindowSize() const
Definition: playground.cc:181
impeller::RenderTarget::SetColorAttachment
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
Definition: render_target.cc:169
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:164
impeller::PlaygroundBackendToString
std::string PlaygroundBackendToString(PlaygroundBackend backend)
Definition: playground.cc:45
formats.h
playground.h
impeller::CompressedImageSkia::Create
static std::shared_ptr< CompressedImage > Create(std::shared_ptr< const fml::Mapping > allocation)
Definition: compressed_image_skia.cc:18
impeller::PlaygroundBackend
PlaygroundBackend
Definition: playground.h:26
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:128
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::RenderTarget::GetColorAttachments
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
Definition: render_target.cc:198
impeller::Playground::MakeContext
std::shared_ptr< Context > MakeContext() const
Definition: playground.cc:94
validation.h
impeller::PlaygroundSwitches::use_swiftshader
bool use_swiftshader
Definition: switches.h:27
impeller::TSize
Definition: size.h:19
render_pass.h
runtime_stage.h
impeller::Playground::RenderCallback
std::function< bool(RenderTarget &render_target)> RenderCallback
Definition: playground.h:80
impeller::Playground
Definition: playground.h:47
impeller::Playground::OpenPlaygroundHere
bool OpenPlaygroundHere(const RenderCallback &render_callback)
Definition: playground.cc:197
impeller::gShouldOpenNewPlaygrounds
static std::atomic_bool gShouldOpenNewPlaygrounds
Definition: playground.cc:158
impeller::Playground::SetupWindow
void SetupWindow()
Definition: playground.cc:137
impeller::TSize::Max
constexpr TSize Max(const TSize &o) const
Definition: size.h:81
impeller::Playground::CreateGLProcAddressResolver
GLProcAddressResolver CreateGLProcAddressResolver() const
Definition: playground.cc:516
impeller::InitializeGLFWOnce
static void InitializeGLFWOnce()
Definition: playground.cc:57
impeller::Playground::switches_
const PlaygroundSwitches switches_
Definition: playground.h:121
impeller::TextureType::kTextureCube
@ kTextureCube
impeller::RenderTarget
Definition: render_target.h:38
impeller::StoreAction::kStore
@ kStore
impeller::Playground::IsPlaygroundEnabled
bool IsPlaygroundEnabled() const
Definition: playground.cc:146
compressed_image_skia.h
impeller::Playground::SinglePassCallback
std::function< bool(RenderPass &pass)> SinglePassCallback
Definition: playground.h:49
impeller::PlaygroundImpl::Create
static std::unique_ptr< PlaygroundImpl > Create(PlaygroundBackend backend, PlaygroundSwitches switches)
Definition: playground_impl.cc:25
impeller::Playground::SetupContext
void SetupContext(PlaygroundBackend backend, const PlaygroundSwitches &switches)
Definition: playground.cc:124
ImGui_ImplImpeller_Shutdown
void ImGui_ImplImpeller_Shutdown()
Definition: imgui_impl_impeller.cc:119
swiftshader_utilities.h
decompressed_image.h
impeller::Playground::~Playground
virtual ~Playground()
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91
command_buffer.h
allocator.h
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:429
playground_impl_vk.h
impeller::Playground::GetContentScale
Point GetContentScale() const
Definition: playground.cc:185
impeller::RenderTarget::SetStencilAttachment
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
Definition: render_target.cc:188
impeller::PlaygroundSwitches
Definition: switches.h:15
impeller::Playground::LoadFixtureImageCompressed
static std::shared_ptr< CompressedImage > LoadFixtureImageCompressed(std::shared_ptr< fml::Mapping > mapping)
Definition: playground.cc:357
impeller::Playground::GetWindowTitle
virtual std::string GetWindowTitle() const =0
impeller::DecompressedImage::GetAllocation
const std::shared_ptr< const fml::Mapping > & GetAllocation() const
Definition: decompressed_image.cc:41
impeller::TPoint< Scalar >
impeller::Playground::OpenAssetAsMapping
virtual std::unique_ptr< fml::Mapping > OpenAssetAsMapping(std::string asset_name) const =0
impeller::Playground::SetCapabilities
fml::Status SetCapabilities(const std::shared_ptr< Capabilities > &capabilities)
Definition: playground.cc:507
impeller::Playground::GetCursorPosition
Point GetCursorPosition() const
Definition: playground.cc:177
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:100
context.h
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:39
ImGui_ImplImpeller_Init
bool ImGui_ImplImpeller_Init(const std::shared_ptr< impeller::Context > &context)
Definition: imgui_impl_impeller.cc:56
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:38
render_target.h
impeller::Playground::TeardownWindow
void TeardownWindow()
Definition: playground.cc:150
impeller::Playground::Playground
Playground(PlaygroundSwitches switches)
Definition: playground.cc:83
impeller::Playground::GetContext
std::shared_ptr< Context > GetContext() const
Definition: playground.cc:90
impeller::TSize::MipCount
constexpr size_t MipCount() const
Definition: size.h:115
impeller::RenderTarget::SetDepthAttachment
RenderTarget & SetDepthAttachment(std::optional< DepthAttachment > attachment)
Definition: render_target.cc:178
playground_impl.h
impeller::Playground::GLProcAddressResolver
std::function< void *(const char *proc_name)> GLProcAddressResolver
Definition: playground.h:117
impeller
Definition: allocation.cc:12
imgui_impl_impeller.h
impeller::Playground::SetWindowSize
void SetWindowSize(ISize size)
Definition: playground.cc:499
impeller::PlaygroundSwitches::enable_playground
bool enable_playground
Definition: switches.h:16
impeller::DecompressedImage::GetSize
const ISize & GetSize() const
Definition: decompressed_image.cc:33
compressed_image.h
impeller::Playground::CreateTextureForFixture
std::shared_ptr< Texture > CreateTextureForFixture(const char *fixture_name, bool enable_mipmapping=false) const
Definition: playground.cc:442