• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright 2022 Google LLC
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/GraphiteDawnWindowContext.h"
9#include "tools/window/mac/WindowContextFactory_mac.h"
10
11#import <Cocoa/Cocoa.h>
12#import <QuartzCore/CAConstraintLayoutManager.h>
13#import <QuartzCore/CAMetalLayer.h>
14
15using skwindow::DisplayParams;
16using skwindow::MacWindowInfo;
17using skwindow::internal::GraphiteDawnWindowContext;
18
19namespace {
20
21class GraphiteDawnMetalWindowContext_mac : public GraphiteDawnWindowContext {
22public:
23    GraphiteDawnMetalWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
24
25    ~GraphiteDawnMetalWindowContext_mac() override;
26
27    bool onInitializeContext() override;
28    void onDestroyContext() override;
29    void resize(int w, int h) override;
30
31private:
32    bool resizeInternal();
33
34    NSView*              fMainView;
35    CAMetalLayer*        fMetalLayer;
36};
37
38GraphiteDawnMetalWindowContext_mac::GraphiteDawnMetalWindowContext_mac(const MacWindowInfo& info,
39                                                                       const DisplayParams& params)
40    : GraphiteDawnWindowContext(params, wgpu::TextureFormat::BGRA8Unorm)
41    , fMainView(info.fMainView) {
42
43    CGFloat backingScaleFactor = skwindow::GetBackingScaleFactor(fMainView);
44    CGSize backingSize = fMainView.bounds.size;
45    this->initializeContext(backingSize.width * backingScaleFactor,
46                            backingSize.height * backingScaleFactor);
47}
48
49GraphiteDawnMetalWindowContext_mac::~GraphiteDawnMetalWindowContext_mac() {
50    this->destroyContext();
51}
52
53bool GraphiteDawnMetalWindowContext_mac::onInitializeContext() {
54    SkASSERT(nil != fMainView);
55
56    auto device = createDevice(wgpu::BackendType::Metal);
57    if (!device) {
58        SkASSERT(device);
59        return false;
60    }
61
62    // Create a CAMetalLayer that covers the whole window that will be passed to
63    // CreateSurface.
64    fMetalLayer = [CAMetalLayer layer];
65    BOOL useVsync = fDisplayParams.fDisableVsync ? NO : YES;
66    fMetalLayer.displaySyncEnabled = useVsync;
67    fMainView.wantsLayer = YES;
68    fMainView.layer = fMetalLayer;
69
70    // Adjust fMetalLayer size based on window size.
71    this->resizeInternal();
72
73    wgpu::SurfaceDescriptorFromMetalLayer surfaceChainedDesc;
74    surfaceChainedDesc.layer = fMetalLayer;
75    wgpu::SurfaceDescriptor surfaceDesc;
76    surfaceDesc.nextInChain = &surfaceChainedDesc;
77
78    auto surface = wgpu::Instance(fInstance->Get()).CreateSurface(&surfaceDesc);
79    if (!surface) {
80        SkASSERT(false);
81        return false;
82    }
83
84
85    fDevice = std::move(device);
86    fSurface = std::move(surface);
87    fSwapChain = this->createSwapChain();
88
89    return true;
90}
91
92void GraphiteDawnMetalWindowContext_mac::onDestroyContext() {}
93
94void GraphiteDawnMetalWindowContext_mac::resize(int w, int h) {
95    if (!this->resizeInternal()) {
96        return;
97    }
98    fSwapChain = this->createSwapChain();
99}
100
101bool GraphiteDawnMetalWindowContext_mac::resizeInternal() {
102    CGFloat backingScaleFactor = skwindow::GetBackingScaleFactor(fMainView);
103    CGSize backingSize = fMainView.bounds.size;
104    backingSize.width *= backingScaleFactor;
105    backingSize.height *= backingScaleFactor;
106
107    fMetalLayer.drawableSize = backingSize;
108    fMetalLayer.contentsScale = backingScaleFactor;
109
110    if (fWidth == backingSize.width && fHeight == backingSize.height) {
111        return false;
112    }
113
114    fWidth = backingSize.width;
115    fHeight = backingSize.height;
116    return true;
117}
118
119}  // anonymous namespace
120
121namespace skwindow {
122
123std::unique_ptr<WindowContext> MakeGraphiteDawnMetalForMac(const MacWindowInfo& info,
124                                                           const DisplayParams& params) {
125    std::unique_ptr<WindowContext> ctx(new GraphiteDawnMetalWindowContext_mac(info, params));
126    if (!ctx->isValid()) {
127        return nullptr;
128    }
129    return ctx;
130}
131
132}  // namespace skwindow
133