a3f18f709edb9e89bec807a803ec7b5a5c97286b
[WebKit-https.git] / Source / WebCore / Modules / webgpu / cocoa / GPUSwapChainMetal.mm
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "GPUSwapChain.h"
28
29 #if ENABLE(WEBGPU)
30
31 #import "GPUDevice.h"
32 #import "GPUTexture.h"
33 #import "GPUTextureFormatEnum.h"
34 #import "Logging.h"
35
36 #import <Metal/Metal.h>
37 #import <QuartzCore/QuartzCore.h>
38 #import <wtf/BlockObjCExceptions.h>
39
40 namespace WebCore {
41
42 RefPtr<GPUSwapChain> GPUSwapChain::create()
43 {
44     PlatformSwapLayerSmartPtr platformLayer;
45
46     BEGIN_BLOCK_OBJC_EXCEPTIONS;
47
48     platformLayer = adoptNS([[CAMetalLayer alloc] init]);
49
50     [platformLayer setOpaque:0];
51     [platformLayer setName:@"WebGPU Layer"];
52
53     // FIXME: For now, default to this usage flag.
54     [platformLayer setFramebufferOnly:YES];
55
56     END_BLOCK_OBJC_EXCEPTIONS;
57
58     if (!platformLayer) {
59         LOG(WebGPU, "GPUSwapChain::create(): Unable to create CAMetalLayer!");
60         return nullptr;
61     }
62
63     return adoptRef(new GPUSwapChain(WTFMove(platformLayer)));
64 }
65
66 GPUSwapChain::GPUSwapChain(PlatformSwapLayerSmartPtr&& platformLayer)
67     : m_platformSwapLayer(WTFMove(platformLayer))
68 {
69 }
70
71 void GPUSwapChain::setDevice(const GPUDevice& device)
72 {
73     if (!device.platformDevice()) {
74         LOG(WebGPU, "GPUSwapChain::setDevice(): MTLDevice does not exist!");
75         return;
76     }
77
78     [m_platformSwapLayer setDevice:device.platformDevice()];
79 }
80
81 static std::optional<PlatformTextureFormat> platformTextureFormatForGPUTextureFormat(GPUTextureFormatEnum format)
82 {
83     switch (format) {
84         case GPUTextureFormatEnum::R8G8B8A8Unorm:
85             return MTLPixelFormatRGBA8Unorm;
86         case GPUTextureFormatEnum::R8G8B8A8Uint:
87             return MTLPixelFormatRGBA8Uint;
88         case GPUTextureFormatEnum::B8G8R8A8Unorm:
89             return MTLPixelFormatBGRA8Unorm;
90         case GPUTextureFormatEnum::D32FloatS8Uint:
91             return MTLPixelFormatDepth32Float_Stencil8;
92         default:
93             LOG(WebGPU, "GPUSwapChain::setFormat(): Invalid texture format specified!");
94             return std::nullopt;
95     }
96 }
97
98 void GPUSwapChain::setFormat(GPUTextureFormatEnum format)
99 {
100     auto result = platformTextureFormatForGPUTextureFormat(format);
101     if (!result)
102         return;
103
104     auto mtlResult = static_cast<MTLPixelFormat>(result.value());
105
106     switch (mtlResult) {
107     case MTLPixelFormatBGRA8Unorm:
108     // FIXME: Add the other supported swap layer formats as they are added to GPU spec.
109     //  MTLPixelFormatBGRA8Unorm_sRGB, MTLPixelFormatRGBA16Float, MTLPixelFormatBGRA10_XR, and MTLPixelFormatBGRA10_XR_sRGB.
110         [m_platformSwapLayer setPixelFormat:mtlResult];
111         return;
112     default:
113         LOG(WebGPU, "GPUSwapChain::setFormat(): Unsupported MTLPixelFormat!");
114     }
115 }
116
117 void GPUSwapChain::reshape(int width, int height)
118 {
119     [m_platformSwapLayer setBounds:CGRectMake(0, 0, width, height)];
120     [m_platformSwapLayer setDrawableSize:CGSizeMake(width, height)];
121 }
122
123 RefPtr<GPUTexture> GPUSwapChain::getNextTexture()
124 {
125     RetainPtr<MTLTexture> mtlTexture;
126
127     if (auto drawable = retainPtr([m_platformSwapLayer nextDrawable]))
128         mtlTexture = retainPtr([drawable texture]);
129
130     if (!mtlTexture) {
131         LOG(WebGPU, "GPUSwapChain::getNextTexture(): Unable to get next MTLTexture!");
132         return nullptr;
133     }
134
135     return GPUTexture::create(WTFMove(mtlTexture));
136 }
137
138 void GPUSwapChain::present()
139 {
140     // FIXME: Unimplemented stub.
141 }
142
143 } // namespace WebCore
144
145 #endif // ENABLE(WEBGPU)