xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.mm (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1//
2// Copyright 2024 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// WindowSurfaceWgpuMetalLayer.cpp:
7//    Defines the class interface for WindowSurfaceWgpuMetalLayer, implementing WindowSurfaceWgpu.
8//
9
10#include "libANGLE/renderer/wgpu/mac/WindowSurfaceWgpuMetalLayer.h"
11
12#include <Metal/Metal.h>
13#include <QuartzCore/CAMetalLayer.h>
14
15#include "libANGLE/Display.h"
16#include "libANGLE/renderer/wgpu/DisplayWgpu.h"
17#include "libANGLE/renderer/wgpu/wgpu_utils.h"
18
19namespace rx
20{
21
22WindowSurfaceWgpuMetalLayer::WindowSurfaceWgpuMetalLayer(const egl::SurfaceState &surfaceState,
23                                                         EGLNativeWindowType window)
24    : WindowSurfaceWgpu(surfaceState, window)
25{}
26
27egl::Error WindowSurfaceWgpuMetalLayer::initialize(const egl::Display *display)
28{
29    // TODO: Use the same Metal device as wgpu
30    mMetalDevice = MTLCreateSystemDefaultDevice();
31
32    return WindowSurfaceWgpu::initialize(display);
33}
34
35void WindowSurfaceWgpuMetalLayer::destroy(const egl::Display *display)
36{
37    WindowSurfaceWgpu::destroy(display);
38    [mMetalDevice release];
39    if (mMetalLayer)
40    {
41        [mMetalLayer removeFromSuperlayer];
42        [mMetalLayer release];
43    }
44}
45
46angle::Result WindowSurfaceWgpuMetalLayer::createWgpuSurface(const egl::Display *display,
47                                                             wgpu::Surface *outSurface)
48    API_AVAILABLE(macosx(10.11))
49{
50    CALayer *layer = reinterpret_cast<CALayer *>(getNativeWindow());
51
52    mMetalLayer        = [[CAMetalLayer alloc] init];
53    mMetalLayer.frame  = CGRectMake(0, 0, layer.frame.size.width, layer.frame.size.height);
54    mMetalLayer.device = mMetalDevice;
55    mMetalLayer.drawableSize =
56        CGSizeMake(mMetalLayer.bounds.size.width * mMetalLayer.contentsScale,
57                   mMetalLayer.bounds.size.height * mMetalLayer.contentsScale);
58    mMetalLayer.framebufferOnly  = NO;
59    mMetalLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
60    mMetalLayer.contentsScale    = layer.contentsScale;
61
62    [layer addSublayer:mMetalLayer];
63
64    wgpu::SurfaceDescriptorFromMetalLayer metalLayerDesc;
65    metalLayerDesc.layer = mMetalLayer;
66
67    wgpu::SurfaceDescriptor surfaceDesc;
68    surfaceDesc.nextInChain = &metalLayerDesc;
69
70    DisplayWgpu *displayWgpu = webgpu::GetImpl(display);
71    wgpu::Instance instance  = displayWgpu->getInstance();
72
73    wgpu::Surface surface = instance.CreateSurface(&surfaceDesc);
74    *outSurface           = surface;
75
76    return angle::Result::Continue;
77}
78
79angle::Result WindowSurfaceWgpuMetalLayer::getCurrentWindowSize(const egl::Display *display,
80                                                                gl::Extents *outSize)
81    API_AVAILABLE(macosx(10.11))
82{
83    ASSERT(mMetalLayer != nullptr);
84
85    mMetalLayer.drawableSize =
86        CGSizeMake(mMetalLayer.bounds.size.width * mMetalLayer.contentsScale,
87                   mMetalLayer.bounds.size.height * mMetalLayer.contentsScale);
88    *outSize = gl::Extents(static_cast<int>(mMetalLayer.drawableSize.width),
89                           static_cast<int>(mMetalLayer.drawableSize.height), 1);
90
91    return angle::Result::Continue;
92}
93
94WindowSurfaceWgpu *CreateWgpuWindowSurface(const egl::SurfaceState &surfaceState,
95                                           EGLNativeWindowType window)
96{
97    return new WindowSurfaceWgpuMetalLayer(surfaceState, window);
98}
99}  // namespace rx
100