1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tools/sk_app/DawnWindowContext.h" 9cb93a386Sopenharmony_ci#include "tools/sk_app/mac/WindowContextFactory_mac.h" 10cb93a386Sopenharmony_ci#include "dawn/webgpu_cpp.h" 11cb93a386Sopenharmony_ci#include "dawn/dawn_wsi.h" 12cb93a386Sopenharmony_ci#include "dawn_native/DawnNative.h" 13cb93a386Sopenharmony_ci#include "dawn_native/MetalBackend.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#import <Metal/Metal.h> 16cb93a386Sopenharmony_ci#import <QuartzCore/CAMetalLayer.h> 17cb93a386Sopenharmony_ci#import <Cocoa/Cocoa.h> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cinamespace sk_app { 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ciusing sk_app::window_context_factory::MacWindowInfo; 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_citemplate <typename T> 24cb93a386Sopenharmony_ciDawnSwapChainImplementation CreateSwapChainImplementation(T* swapChain) { 25cb93a386Sopenharmony_ci DawnSwapChainImplementation impl = {}; 26cb93a386Sopenharmony_ci impl.userData = swapChain; 27cb93a386Sopenharmony_ci impl.Init = [](void* userData, void* wsiContext) { 28cb93a386Sopenharmony_ci auto* ctx = static_cast<typename T::WSIContext*>(wsiContext); 29cb93a386Sopenharmony_ci reinterpret_cast<T*>(userData)->Init(ctx); 30cb93a386Sopenharmony_ci }; 31cb93a386Sopenharmony_ci impl.Destroy = [](void* userData) { delete reinterpret_cast<T*>(userData); }; 32cb93a386Sopenharmony_ci impl.Configure = [](void* userData, WGPUTextureFormat format, WGPUTextureUsage allowedUsage, 33cb93a386Sopenharmony_ci uint32_t width, uint32_t height) { 34cb93a386Sopenharmony_ci return static_cast<T*>(userData)->Configure(format, allowedUsage, width, height); 35cb93a386Sopenharmony_ci }; 36cb93a386Sopenharmony_ci impl.GetNextTexture = [](void* userData, DawnSwapChainNextTexture* nextTexture) { 37cb93a386Sopenharmony_ci return static_cast<T*>(userData)->GetNextTexture(nextTexture); 38cb93a386Sopenharmony_ci }; 39cb93a386Sopenharmony_ci impl.Present = [](void* userData) { return static_cast<T*>(userData)->Present(); }; 40cb93a386Sopenharmony_ci return impl; 41cb93a386Sopenharmony_ci} 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ciclass DawnMTLWindowContext : public DawnWindowContext { 44cb93a386Sopenharmony_cipublic: 45cb93a386Sopenharmony_ci DawnMTLWindowContext(const MacWindowInfo& info, const DisplayParams& params); 46cb93a386Sopenharmony_ci ~DawnMTLWindowContext() override; 47cb93a386Sopenharmony_ci wgpu::Device onInitializeContext() override; 48cb93a386Sopenharmony_ci void onDestroyContext() override; 49cb93a386Sopenharmony_ci DawnSwapChainImplementation createSwapChainImplementation(int width, int height, 50cb93a386Sopenharmony_ci const DisplayParams& params) override; 51cb93a386Sopenharmony_ci void onSwapBuffers() override; 52cb93a386Sopenharmony_ciprivate: 53cb93a386Sopenharmony_ci NSView* fMainView; 54cb93a386Sopenharmony_ci id<MTLDevice> fMTLDevice; 55cb93a386Sopenharmony_ci CAMetalLayer* fLayer; 56cb93a386Sopenharmony_ci}; 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ciclass SwapChainImplMTL { 59cb93a386Sopenharmony_cipublic: 60cb93a386Sopenharmony_ci typedef void WSIContext; 61cb93a386Sopenharmony_ci static DawnSwapChainImplementation Create(id<MTLDevice> device, CAMetalLayer* layer) { 62cb93a386Sopenharmony_ci auto impl = new SwapChainImplMTL(device, layer); 63cb93a386Sopenharmony_ci return CreateSwapChainImplementation<SwapChainImplMTL>(impl); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci void Init(WSIContext* ctx) {} 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci SwapChainImplMTL(id<MTLDevice> device, CAMetalLayer* layer) 69cb93a386Sopenharmony_ci : fQueue([device newCommandQueue]) 70cb93a386Sopenharmony_ci , fLayer(layer) {} 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci ~SwapChainImplMTL() {} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci DawnSwapChainError Configure(WGPUTextureFormat format, WGPUTextureUsage, 75cb93a386Sopenharmony_ci uint32_t width, uint32_t height) { 76cb93a386Sopenharmony_ci if (format != WGPUTextureFormat::WGPUTextureFormat_RGBA8Unorm) { 77cb93a386Sopenharmony_ci return "unsupported format"; 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci SkASSERT(width > 0); 80cb93a386Sopenharmony_ci SkASSERT(height > 0); 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci return DAWN_SWAP_CHAIN_NO_ERROR; 83cb93a386Sopenharmony_ci } 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture) { 86cb93a386Sopenharmony_ci fCurrentDrawable = [fLayer nextDrawable]; 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci nextTexture->texture.ptr = reinterpret_cast<void*>(fCurrentDrawable.texture); 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci return DAWN_SWAP_CHAIN_NO_ERROR; 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci DawnSwapChainError Present() { 94cb93a386Sopenharmony_ci id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer]; 95cb93a386Sopenharmony_ci [commandBuffer presentDrawable: fCurrentDrawable]; 96cb93a386Sopenharmony_ci [commandBuffer commit]; 97cb93a386Sopenharmony_ci return DAWN_SWAP_CHAIN_NO_ERROR; 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ciprivate: 100cb93a386Sopenharmony_ci id<MTLCommandQueue> fQueue; 101cb93a386Sopenharmony_ci CAMetalLayer* fLayer; 102cb93a386Sopenharmony_ci id<CAMetalDrawable> fCurrentDrawable = nil; 103cb93a386Sopenharmony_ci}; 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ciDawnMTLWindowContext::DawnMTLWindowContext(const MacWindowInfo& info, const DisplayParams& params) 106cb93a386Sopenharmony_ci : DawnWindowContext(params, wgpu::TextureFormat::BGRA8Unorm) 107cb93a386Sopenharmony_ci , fMainView(info.fMainView) { 108cb93a386Sopenharmony_ci CGSize size = fMainView.bounds.size; 109cb93a386Sopenharmony_ci this->initializeContext(size.width, size.height); 110cb93a386Sopenharmony_ci} 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ciDawnMTLWindowContext::~DawnMTLWindowContext() { 113cb93a386Sopenharmony_ci this->destroyContext(); 114cb93a386Sopenharmony_ci} 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ciDawnSwapChainImplementation DawnMTLWindowContext::createSwapChainImplementation( 117cb93a386Sopenharmony_ci int width, int height, const DisplayParams& params) { 118cb93a386Sopenharmony_ci return SwapChainImplMTL::Create(fMTLDevice, fLayer); 119cb93a386Sopenharmony_ci} 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ciwgpu::Device DawnMTLWindowContext::onInitializeContext() { 122cb93a386Sopenharmony_ci wgpu::Device device = this->createDevice(dawn_native::BackendType::Metal); 123cb93a386Sopenharmony_ci if (!device) { 124cb93a386Sopenharmony_ci return nullptr; 125cb93a386Sopenharmony_ci } 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci fMTLDevice = dawn_native::metal::GetMetalDevice(device.Get()); 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci CGSize size; 130cb93a386Sopenharmony_ci size.width = width(); 131cb93a386Sopenharmony_ci size.height = height(); 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci fLayer = [CAMetalLayer layer]; 134cb93a386Sopenharmony_ci [fLayer setDevice:fMTLDevice]; 135cb93a386Sopenharmony_ci [fLayer setPixelFormat: MTLPixelFormatBGRA8Unorm]; 136cb93a386Sopenharmony_ci [fLayer setFramebufferOnly: YES]; 137cb93a386Sopenharmony_ci [fLayer setDrawableSize: size]; 138cb93a386Sopenharmony_ci [fLayer setColorspace: CGColorSpaceCreateDeviceRGB()]; 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci [fMainView setWantsLayer: YES]; 141cb93a386Sopenharmony_ci [fMainView setLayer: fLayer]; 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci return device; 144cb93a386Sopenharmony_ci} 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_civoid DawnMTLWindowContext::onDestroyContext() { 147cb93a386Sopenharmony_ci} 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_civoid DawnMTLWindowContext::onSwapBuffers() { 150cb93a386Sopenharmony_ci} 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_cinamespace window_context_factory { 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_cistd::unique_ptr<WindowContext> MakeDawnMTLForMac(const MacWindowInfo& winInfo, 155cb93a386Sopenharmony_ci const DisplayParams& params) { 156cb93a386Sopenharmony_ci std::unique_ptr<WindowContext> ctx(new DawnMTLWindowContext(winInfo, params)); 157cb93a386Sopenharmony_ci if (!ctx->isValid()) { 158cb93a386Sopenharmony_ci return nullptr; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci return ctx; 161cb93a386Sopenharmony_ci} 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci} 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci} //namespace sk_app 166