17#define GLFW_INCLUDE_NONE
18#include "third_party/glfw/include/GLFW/glfw3.h"
20#include "flutter/fml/paths.h"
32#include "third_party/imgui/backends/imgui_impl_glfw.h"
33#include "third_party/imgui/imgui.h"
39#if IMPELLER_ENABLE_VULKAN
74 static std::once_flag sOnceInitializer;
75 std::call_once(sOnceInitializer, []() {
76 ::glfwSetErrorCallback([](
int code,
const char* description) {
103#if IMPELLER_ENABLE_METAL
109#if IMPELLER_ENABLE_OPENGLES
115#if IMPELLER_ENABLE_VULKAN
130 FML_LOG(WARNING) <<
"PlaygroundImpl::Create failed.";
134 context_ = impl_->GetContext();
139 FML_LOG(WARNING) <<
"Asked to set up a window with no context (call "
140 "SetupContext first).";
143 auto renderer = std::make_unique<Renderer>(context_);
158 context_->Shutdown();
176 if ((
key == GLFW_KEY_ESCAPE) &&
action == GLFW_RELEASE) {
177 if (mods & (GLFW_MOD_CONTROL | GLFW_MOD_SUPER | GLFW_MOD_SHIFT)) {
185 return cursor_position_;
193 return impl_->GetContentScale();
200void Playground::SetCursorPosition(
Point pos) {
201 cursor_position_ =
pos;
210 if (!render_callback) {
214 if (!renderer_ || !renderer_->IsValid()) {
218 IMGUI_CHECKVERSION();
221 []() { ImGui::DestroyContext(); });
222 ImGui::StyleColorsDark();
224 auto& io = ImGui::GetIO();
225 io.IniFilename =
nullptr;
226 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
227 io.ConfigWindowsResizeFromEdges =
true;
229 auto window =
reinterpret_cast<GLFWwindow*
>(impl_->GetWindowHandle());
234 ::glfwSetWindowUserPointer(
window,
this);
235 ::glfwSetWindowSizeCallback(
245 ::glfwSetCursorPosCallback(
window, [](GLFWwindow*
window,
double x,
248 ->SetCursorPosition({
static_cast<Scalar>(
x),
static_cast<Scalar>(
y)});
251 ImGui_ImplGlfw_InitForOther(
window,
true);
258 ImGui::SetNextWindowPos({10, 10});
261 ::glfwSetWindowPos(
window, 200, 100);
270 if (::glfwWindowShouldClose(
window)) {
274 ImGui_ImplGlfw_NewFrame();
280 ImGui::DockSpaceOverViewport(ImGui::GetMainViewport(),
281 ImGuiDockNodeFlags_PassthruCentralNode);
282 bool result = render_callback(render_target);
291 buffer->SetLabel(
"ImGui Command Buffer");
293 if (render_target.GetColorAttachments().empty()) {
297 auto color0 = render_target.GetColorAttachments().find(0)->second;
299 if (color0.resolve_texture) {
300 color0.texture = color0.resolve_texture;
301 color0.resolve_texture =
nullptr;
304 render_target.SetColorAttachment(color0, 0);
306 render_target.SetStencilAttachment(std::nullopt);
307 render_target.SetDepthAttachment(std::nullopt);
309 auto pass =
buffer->CreateRenderPass(render_target);
313 pass->SetLabel(
"ImGui Render Pass");
317 pass->EncodeCommands();
318 if (!
renderer->GetContext()->GetCommandQueue()->Submit({buffer}).ok()) {
326 if (!renderer_->Render(impl_->AcquireSurfaceFrame(renderer_->GetContext()),
345 auto buffer = context->CreateCommandBuffer();
349 buffer->SetLabel(
"Playground Command Buffer");
351 auto pass =
buffer->CreateRenderPass(render_target);
355 pass->SetLabel(
"Playground Render Pass");
357 if (!pass_callback(*pass)) {
361 pass->EncodeCommands();
362 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
370 std::shared_ptr<fml::Mapping> mapping) {
372 if (!compressed_image) {
377 return compressed_image;
381 const std::shared_ptr<CompressedImage>& compressed) {
382 if (compressed ==
nullptr) {
390 auto image = compressed->Decode().ConvertToRGBA();
391 if (!
image.IsValid()) {
400 const std::shared_ptr<Context>& context,
402 bool enable_mipmapping) {
406 texture_descriptor.size = decompressed_image.
GetSize();
407 texture_descriptor.mip_count =
411 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
417 auto command_buffer = context->CreateCommandBuffer();
418 if (!command_buffer) {
419 FML_DLOG(
ERROR) <<
"Could not create command buffer for mipmap generation.";
422 command_buffer->SetLabel(
"Mipmap Command Buffer");
424 auto blit_pass = command_buffer->CreateBlitPass();
426 context->GetResourceAllocator()->CreateBufferWithCopy(
429 if (enable_mipmapping) {
430 blit_pass->SetLabel(
"Mipmap Blit Pass");
431 blit_pass->GenerateMipmap(
texture);
433 blit_pass->EncodeCommands(context->GetResourceAllocator());
434 if (!context->GetCommandQueue()->Submit({command_buffer}).ok()) {
435 FML_DLOG(
ERROR) <<
"Failed to submit blit pass command buffer.";
442 const std::shared_ptr<Context>& context,
443 std::shared_ptr<fml::Mapping> mapping,
444 bool enable_mipmapping) {
447 if (!
image.has_value()) {
455 const char* fixture_name,
456 bool enable_mipmapping)
const {
463 texture->SetLabel(fixture_name);
468 std::array<const char*, 6> fixture_names)
const {
469 std::array<DecompressedImage, 6>
images;
470 for (
size_t i = 0;
i < fixture_names.size();
i++) {
473 if (!
image.has_value()) {
483 texture_descriptor.size =
images[0].GetSize();
484 texture_descriptor.mip_count = 1u;
486 auto texture = renderer_->GetContext()->GetResourceAllocator()->CreateTexture(
492 texture->SetLabel(
"Texture cube");
494 auto cmd_buffer = renderer_->GetContext()->CreateCommandBuffer();
495 auto blit_pass = cmd_buffer->CreateBlitPass();
496 for (
size_t i = 0;
i < fixture_names.size();
i++) {
498 renderer_->GetContext()->GetResourceAllocator()->CreateBufferWithCopy(
504 if (!blit_pass->EncodeCommands(
505 renderer_->GetContext()->GetResourceAllocator()) ||
506 !renderer_->GetContext()
508 ->Submit({std::move(cmd_buffer)})
526 const std::shared_ptr<Capabilities>& capabilities) {
527 return impl_->SetCapabilities(capabilities);
Wraps a closure that is invoked in the destructor unless released by the caller.
TimeDelta ToEpochDelta() const
static std::shared_ptr< CompressedImage > Create(std::shared_ptr< const fml::Mapping > allocation)
const std::shared_ptr< const fml::Mapping > & GetAllocation() const
const ISize & GetSize() const
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
static bool IsVulkanDriverPresent()
static std::unique_ptr< PlaygroundImpl > Create(PlaygroundBackend backend, PlaygroundSwitches switches)
Playground(PlaygroundSwitches switches)
std::shared_ptr< Context > MakeContext() const
bool IsPlaygroundEnabled() const
virtual bool ShouldKeepRendering() const
static bool ShouldOpenNewPlaygrounds()
Point GetCursorPosition() const
void SetWindowSize(ISize size)
static std::shared_ptr< CompressedImage > LoadFixtureImageCompressed(std::shared_ptr< fml::Mapping > mapping)
ISize GetWindowSize() const
std::function< bool(RenderPass &pass)> SinglePassCallback
void SetupContext(PlaygroundBackend backend, const PlaygroundSwitches &switches)
bool WillRenderSomething() const
virtual std::string GetWindowTitle() const =0
const PlaygroundSwitches switches_
std::shared_ptr< Context > GetContext() const
bool OpenPlaygroundHere(const Renderer::RenderCallback &render_callback)
static bool SupportsBackend(PlaygroundBackend backend)
static std::shared_ptr< Texture > CreateTextureForMapping(const std::shared_ptr< Context > &context, std::shared_ptr< fml::Mapping > mapping, bool enable_mipmapping=false)
virtual std::unique_ptr< fml::Mapping > OpenAssetAsMapping(std::string asset_name) const =0
Point GetContentScale() const
std::shared_ptr< Texture > CreateTextureForFixture(const char *fixture_name, bool enable_mipmapping=false) const
Scalar GetSecondsElapsed() const
Get the amount of time elapsed from the start of the playground's execution.
static std::optional< DecompressedImage > DecodeImageRGBA(const std::shared_ptr< CompressedImage > &compressed)
std::shared_ptr< Texture > CreateTextureCubeForFixture(std::array< const char *, 6 > fixture_names) const
fml::Status SetCapabilities(const std::shared_ptr< Capabilities > &capabilities)
std::function< bool(RenderTarget &render_target)> RenderCallback
#define FML_DLOG(severity)
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_UNREACHABLE()
bool ImGui_ImplImpeller_Init(const std::shared_ptr< impeller::Context > &context)
void ImGui_ImplImpeller_RenderDrawData(ImDrawData *draw_data, impeller::RenderPass &render_pass)
void ImGui_ImplImpeller_Shutdown()
std::array< MockImage, 3 > images
sk_sp< const SkImage > image
static EGLResult< EGLContext > CreateContext(EGLDisplay display, EGLConfig config, EGLContext share=EGL_NO_CONTEXT)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static std::shared_ptr< Texture > CreateTextureForDecompressedImage(const std::shared_ptr< Context > &context, DecompressedImage &decompressed_image, bool enable_mipmapping)
std::string PlaygroundBackendToString(PlaygroundBackend backend)
static void PlaygroundKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
static void InitializeGLFWOnce()
static std::atomic_bool gShouldOpenNewPlaygrounds
void SetupSwiftshaderOnce(bool use_swiftshader)
Find and setup the installable client driver for a locally built SwiftShader at known paths....
constexpr size_t MipCount() const
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...