• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/sk_app/MetalWindowContext.h"
9#include "tools/sk_app/mac/WindowContextFactory_mac.h"
10
11#import <Cocoa/Cocoa.h>
12#import <QuartzCore/CAConstraintLayoutManager.h>
13
14using sk_app::DisplayParams;
15using sk_app::window_context_factory::MacWindowInfo;
16using sk_app::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    using INHERITED = MetalWindowContext;
35};
36
37MetalWindowContext_mac::MetalWindowContext_mac(const MacWindowInfo& info,
38                                               const DisplayParams& params)
39    : INHERITED(params)
40    , fMainView(info.fMainView) {
41
42    // any config code here (particularly for msaa)?
43
44    this->initializeContext();
45}
46
47MetalWindowContext_mac::~MetalWindowContext_mac() {
48    this->destroyContext();
49}
50
51bool MetalWindowContext_mac::onInitializeContext() {
52    SkASSERT(nil != fMainView);
53
54    fMetalLayer = [CAMetalLayer layer];
55    fMetalLayer.device = fDevice.get();
56    fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
57
58    // resize ignores the passed values and uses the fMainView directly.
59    this->resize(0, 0);
60
61    BOOL useVsync = fDisplayParams.fDisableVsync ? NO : YES;
62    fMetalLayer.displaySyncEnabled = useVsync;  // TODO: need solution for 10.12 or lower
63    fMetalLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
64    fMetalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
65    fMetalLayer.contentsGravity = kCAGravityTopLeft;
66    fMetalLayer.magnificationFilter = kCAFilterNearest;
67    NSColorSpace* cs = fMainView.window.colorSpace;
68    fMetalLayer.colorspace = cs.CGColorSpace;
69
70    fMainView.layer = fMetalLayer;
71    fMainView.wantsLayer = YES;
72
73    return true;
74}
75
76void MetalWindowContext_mac::onDestroyContext() {
77    fMainView.layer = nil;
78    fMainView.wantsLayer = NO;
79}
80
81void MetalWindowContext_mac::resize(int w, int h) {
82    CGFloat backingScaleFactor = sk_app::GetBackingScaleFactor(fMainView);
83    CGSize backingSize = fMainView.bounds.size;
84    backingSize.width *= backingScaleFactor;
85    backingSize.height *= backingScaleFactor;
86
87    fMetalLayer.drawableSize = backingSize;
88    fMetalLayer.contentsScale = backingScaleFactor;
89
90    fWidth = backingSize.width;
91    fHeight = backingSize.height;
92}
93
94}  // anonymous namespace
95
96namespace sk_app {
97namespace window_context_factory {
98
99std::unique_ptr<WindowContext> MakeMetalForMac(const MacWindowInfo& info,
100                                               const DisplayParams& params) {
101    std::unique_ptr<WindowContext> ctx(new MetalWindowContext_mac(info, params));
102    if (!ctx->isValid()) {
103        return nullptr;
104    }
105    return ctx;
106}
107
108}  // namespace window_context_factory
109}  // namespace sk_app
110