blob: c400e62a9f7a5bba55a7ef90d8f4b7c915fa448c [file] [log] [blame]
// 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/backend/metal/playground_impl_mtl.h"
#define GLFW_INCLUDE_NONE
#import "third_party/glfw/include/GLFW/glfw3.h"
#define GLFW_EXPOSE_NATIVE_COCOA
#import "third_party/glfw/include/GLFW/glfw3native.h"
#include <Metal/Metal.h>
#include <QuartzCore/QuartzCore.h>
#include "flutter/fml/mapping.h"
#include "impeller/entity/mtl/entity_shaders.h"
#include "impeller/entity/mtl/modern_shaders.h"
#include "impeller/fixtures/mtl/fixtures_shaders.h"
#include "impeller/playground/imgui/mtl/imgui_shaders.h"
#include "impeller/renderer/backend/metal/context_mtl.h"
#include "impeller/renderer/backend/metal/formats_mtl.h"
#include "impeller/renderer/backend/metal/surface_mtl.h"
#include "impeller/renderer/backend/metal/texture_mtl.h"
namespace impeller {
struct PlaygroundImplMTL::Data {
CAMetalLayer* metal_layer = nil;
};
static std::vector<std::shared_ptr<fml::Mapping>>
ShaderLibraryMappingsForPlayground() {
return {
std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_data,
impeller_entity_shaders_length),
std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_data,
impeller_modern_shaders_length),
std::make_shared<fml::NonOwnedMapping>(impeller_fixtures_shaders_data,
impeller_fixtures_shaders_length),
std::make_shared<fml::NonOwnedMapping>(impeller_imgui_shaders_data,
impeller_imgui_shaders_length),
};
}
void PlaygroundImplMTL::DestroyWindowHandle(WindowHandle handle) {
if (!handle) {
return;
}
::glfwDestroyWindow(reinterpret_cast<GLFWwindow*>(handle));
}
PlaygroundImplMTL::PlaygroundImplMTL()
: handle_(nullptr, &DestroyWindowHandle), data_(std::make_unique<Data>()) {
::glfwDefaultWindowHints();
::glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
::glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
auto window = ::glfwCreateWindow(1, 1, "Test", nullptr, nullptr);
if (!window) {
return;
}
auto context = ContextMTL::Create(ShaderLibraryMappingsForPlayground(),
"Playground Library");
if (!context) {
return;
}
NSWindow* cocoa_window = ::glfwGetCocoaWindow(window);
if (cocoa_window == nil) {
return;
}
data_->metal_layer = [CAMetalLayer layer];
data_->metal_layer.device = ContextMTL::Cast(*context).GetMTLDevice();
// This pixel format is one of the documented supported formats.
data_->metal_layer.pixelFormat = ToMTLPixelFormat(PixelFormat::kDefaultColor);
data_->metal_layer.framebufferOnly = NO;
cocoa_window.contentView.layer = data_->metal_layer;
cocoa_window.contentView.wantsLayer = YES;
handle_.reset(window);
context_ = std::move(context);
}
PlaygroundImplMTL::~PlaygroundImplMTL() = default;
std::shared_ptr<Context> PlaygroundImplMTL::GetContext() const {
return context_;
}
// |PlaygroundImpl|
PlaygroundImpl::WindowHandle PlaygroundImplMTL::GetWindowHandle() const {
return handle_.get();
}
// |PlaygroundImpl|
std::unique_ptr<Surface> PlaygroundImplMTL::AcquireSurfaceFrame(
std::shared_ptr<Context> context) {
if (!data_->metal_layer) {
return nullptr;
}
const auto layer_size = data_->metal_layer.bounds.size;
const auto scale = GetContentScale();
data_->metal_layer.drawableSize =
CGSizeMake(layer_size.width * scale.x, layer_size.height * scale.y);
return SurfaceMTL::WrapCurrentMetalLayerDrawable(context, data_->metal_layer);
}
} // namespace impeller