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