1/* 2 * Copyright 2019 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "tools/window/MetalWindowContext.h" 9#include "tools/window/mac/WindowContextFactory_mac.h" 10 11#import <Cocoa/Cocoa.h> 12#import <QuartzCore/CAConstraintLayoutManager.h> 13 14using skwindow::DisplayParams; 15using skwindow::MacWindowInfo; 16using skwindow::internal::MetalWindowContext; 17 18namespace { 19 20class MetalWindowContext_mac : public MetalWindowContext { 21public: 22 MetalWindowContext_mac(const MacWindowInfo&, const DisplayParams&); 23 24 ~MetalWindowContext_mac() override; 25 26 bool onInitializeContext() override; 27 void onDestroyContext() override; 28 29 void resize(int w, int h) override; 30 31private: 32 NSView* fMainView; 33}; 34 35MetalWindowContext_mac::MetalWindowContext_mac(const MacWindowInfo& info, 36 const DisplayParams& params) 37 : MetalWindowContext(params) 38 , fMainView(info.fMainView) { 39 40 // any config code here (particularly for msaa)? 41 42 this->initializeContext(); 43} 44 45MetalWindowContext_mac::~MetalWindowContext_mac() { 46 this->destroyContext(); 47} 48 49bool MetalWindowContext_mac::onInitializeContext() { 50 SkASSERT(nil != fMainView); 51 52 fMetalLayer = [CAMetalLayer layer]; 53 fMetalLayer.device = fDevice.get(); 54 fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; 55 56 // resize ignores the passed values and uses the fMainView directly. 57 this->resize(0, 0); 58 59 BOOL useVsync = fDisplayParams.fDisableVsync ? NO : YES; 60 fMetalLayer.displaySyncEnabled = useVsync; // TODO: need solution for 10.12 or lower 61 fMetalLayer.layoutManager = [CAConstraintLayoutManager layoutManager]; 62 fMetalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable; 63 fMetalLayer.contentsGravity = kCAGravityTopLeft; 64 fMetalLayer.magnificationFilter = kCAFilterNearest; 65 NSColorSpace* cs = fMainView.window.colorSpace; 66 fMetalLayer.colorspace = cs.CGColorSpace; 67 68 fMainView.layer = fMetalLayer; 69 fMainView.wantsLayer = YES; 70 71 return true; 72} 73 74void MetalWindowContext_mac::onDestroyContext() {} 75 76void MetalWindowContext_mac::resize(int w, int h) { 77 CGFloat backingScaleFactor = skwindow::GetBackingScaleFactor(fMainView); 78 CGSize backingSize = fMainView.bounds.size; 79 backingSize.width *= backingScaleFactor; 80 backingSize.height *= backingScaleFactor; 81 82 fMetalLayer.drawableSize = backingSize; 83 fMetalLayer.contentsScale = backingScaleFactor; 84 85 fWidth = backingSize.width; 86 fHeight = backingSize.height; 87} 88 89} // anonymous namespace 90 91namespace skwindow { 92 93std::unique_ptr<WindowContext> MakeMetalForMac(const MacWindowInfo& info, 94 const DisplayParams& params) { 95 std::unique_ptr<WindowContext> ctx(new MetalWindowContext_mac(info, params)); 96 if (!ctx->isValid()) { 97 return nullptr; 98 } 99 return ctx; 100} 101 102} // namespace skwindow 103