blob: 2ce22f3c25aa1025bd8159e9cef8a7a5c2008a68 [file] [log] [blame]
/*
* 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