| /* |
| * Copyright 2019 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "tools/sk_app/DawnWindowContext.h" |
| #include "tools/sk_app/mac/WindowContextFactory_mac.h" |
| #include "common/SwapChainUtils.h" |
| #include "dawn/dawncpp.h" |
| #include "dawn/dawn_wsi.h" |
| #include "dawn_native/DawnNative.h" |
| #include "dawn_native/MetalBackend.h" |
| |
| #import <Metal/Metal.h> |
| #import <QuartzCore/CAMetalLayer.h> |
| #import <Cocoa/Cocoa.h> |
| |
| namespace sk_app { |
| |
| using sk_app::window_context_factory::MacWindowInfo; |
| |
| class DawnMTLWindowContext : public DawnWindowContext { |
| public: |
| DawnMTLWindowContext(const MacWindowInfo& info, const DisplayParams& params); |
| ~DawnMTLWindowContext() override; |
| dawn::Device onInitializeContext() override; |
| void onDestroyContext() override; |
| DawnSwapChainImplementation createSwapChainImplementation(int width, int height, |
| const DisplayParams& params) override; |
| void onSwapBuffers() override; |
| private: |
| NSView* fMainView; |
| id<MTLDevice> fMTLDevice; |
| CAMetalLayer* fLayer; |
| }; |
| |
| class SwapChainImplMTL { |
| public: |
| typedef void WSIContext; |
| static DawnSwapChainImplementation Create(id<MTLDevice> device, CAMetalLayer* layer) { |
| auto impl = new SwapChainImplMTL(device, layer); |
| return CreateSwapChainImplementation<SwapChainImplMTL>(impl); |
| } |
| |
| void Init(WSIContext* ctx) {} |
| |
| SwapChainImplMTL(id<MTLDevice> device, CAMetalLayer* layer) |
| : fQueue([device newCommandQueue]) |
| , fLayer(layer) {} |
| |
| ~SwapChainImplMTL() {} |
| |
| DawnSwapChainError Configure(DawnTextureFormat format, DawnTextureUsage, |
| uint32_t width, uint32_t height) { |
| if (format != DAWN_TEXTURE_FORMAT_RGBA8_UNORM) { |
| return "unsupported format"; |
| } |
| SkASSERT(width > 0); |
| SkASSERT(height > 0); |
| |
| return DAWN_SWAP_CHAIN_NO_ERROR; |
| } |
| |
| DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture) { |
| fCurrentDrawable = [fLayer nextDrawable]; |
| |
| nextTexture->texture.ptr = reinterpret_cast<void*>(fCurrentDrawable.texture); |
| |
| return DAWN_SWAP_CHAIN_NO_ERROR; |
| } |
| |
| DawnSwapChainError Present() { |
| id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer]; |
| [commandBuffer presentDrawable: fCurrentDrawable]; |
| [commandBuffer commit]; |
| return DAWN_SWAP_CHAIN_NO_ERROR; |
| } |
| private: |
| id<MTLCommandQueue> fQueue; |
| CAMetalLayer* fLayer; |
| id<CAMetalDrawable> fCurrentDrawable = nil; |
| }; |
| |
| DawnMTLWindowContext::DawnMTLWindowContext(const MacWindowInfo& info, const DisplayParams& params) |
| : DawnWindowContext(params, dawn::TextureFormat::BGRA8Unorm) |
| , fMainView(info.fMainView) { |
| CGSize size = fMainView.bounds.size; |
| this->initializeContext(size.width, size.height); |
| } |
| |
| DawnMTLWindowContext::~DawnMTLWindowContext() { |
| this->destroyContext(); |
| } |
| |
| DawnSwapChainImplementation DawnMTLWindowContext::createSwapChainImplementation( |
| int width, int height, const DisplayParams& params) { |
| return SwapChainImplMTL::Create(fMTLDevice, fLayer); |
| } |
| |
| dawn::Device DawnMTLWindowContext::onInitializeContext() { |
| dawn::Device device = this->createDevice(dawn_native::BackendType::Metal); |
| if (!device) { |
| return nullptr; |
| } |
| |
| fMTLDevice = dawn_native::metal::GetMetalDevice(device.Get()); |
| |
| CGSize size; |
| size.width = width(); |
| size.height = height(); |
| |
| fLayer = [CAMetalLayer layer]; |
| [fLayer setDevice:fMTLDevice]; |
| [fLayer setPixelFormat: MTLPixelFormatBGRA8Unorm]; |
| [fLayer setFramebufferOnly: YES]; |
| [fLayer setDrawableSize: size]; |
| [fLayer setColorspace: CGColorSpaceCreateDeviceRGB()]; |
| |
| [fMainView setWantsLayer: YES]; |
| [fMainView setLayer: fLayer]; |
| |
| return device; |
| } |
| |
| void DawnMTLWindowContext::onDestroyContext() { |
| } |
| |
| void DawnMTLWindowContext::onSwapBuffers() { |
| } |
| |
| namespace window_context_factory { |
| |
| std::unique_ptr<WindowContext> MakeDawnMTLForMac(const MacWindowInfo& winInfo, |
| const DisplayParams& params) { |
| std::unique_ptr<WindowContext> ctx(new DawnMTLWindowContext(winInfo, params)); |
| if (!ctx->isValid()) { |
| return nullptr; |
| } |
| return ctx; |
| } |
| |
| } |
| |
| } //namespace sk_app |