xref: /aosp_15_r20/external/skia/tools/window/mac/GraphiteDawnMetalWindowContext_mac.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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#include "tools/window/mac/GraphiteDawnMetalWindowContext_mac.h"
8
9#include "tools/window/GraphiteDawnWindowContext.h"
10#include "tools/window/mac/MacWindowInfo.h"
11
12#import <Cocoa/Cocoa.h>
13#import <QuartzCore/CAConstraintLayoutManager.h>
14#import <QuartzCore/CAMetalLayer.h>
15
16using skwindow::DisplayParams;
17using skwindow::MacWindowInfo;
18using skwindow::internal::GraphiteDawnWindowContext;
19
20namespace {
21
22class GraphiteDawnMetalWindowContext_mac : public GraphiteDawnWindowContext {
23public:
24    GraphiteDawnMetalWindowContext_mac(const MacWindowInfo&, std::unique_ptr<const DisplayParams>);
25
26    ~GraphiteDawnMetalWindowContext_mac() override;
27
28    bool onInitializeContext() override;
29    void onDestroyContext() override;
30    void resize(int w, int h) override;
31
32private:
33    bool resizeInternal();
34
35    NSView*              fMainView;
36    CAMetalLayer*        fMetalLayer;
37};
38
39GraphiteDawnMetalWindowContext_mac::GraphiteDawnMetalWindowContext_mac(
40        const MacWindowInfo& info, std::unique_ptr<const DisplayParams> params)
41        : GraphiteDawnWindowContext(std::move(params), wgpu::TextureFormat::BGRA8Unorm)
42        , fMainView(info.fMainView) {
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->disableVsync() ? 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    fDevice = std::move(device);
85    fSurface = std::move(surface);
86    configureSurface();
87
88    return true;
89}
90
91void GraphiteDawnMetalWindowContext_mac::onDestroyContext() {}
92
93void GraphiteDawnMetalWindowContext_mac::resize(int w, int h) {
94    if (!this->resizeInternal()) {
95        return;
96    }
97}
98
99bool GraphiteDawnMetalWindowContext_mac::resizeInternal() {
100    CGFloat backingScaleFactor = skwindow::GetBackingScaleFactor(fMainView);
101    CGSize backingSize = fMainView.bounds.size;
102    backingSize.width *= backingScaleFactor;
103    backingSize.height *= backingScaleFactor;
104
105    fMetalLayer.drawableSize = backingSize;
106    fMetalLayer.contentsScale = backingScaleFactor;
107
108    if (fWidth == backingSize.width && fHeight == backingSize.height) {
109        return false;
110    }
111
112    fWidth = backingSize.width;
113    fHeight = backingSize.height;
114    configureSurface();
115
116    return true;
117}
118
119}  // anonymous namespace
120
121namespace skwindow {
122
123std::unique_ptr<WindowContext> MakeGraphiteDawnMetalForMac(
124        const MacWindowInfo& info, std::unique_ptr<const DisplayParams> params) {
125    std::unique_ptr<WindowContext> ctx(
126            new GraphiteDawnMetalWindowContext_mac(info, std::move(params)));
127    if (!ctx->isValid()) {
128        return nullptr;
129    }
130    return ctx;
131}
132
133}  // namespace skwindow
134