blob: ba398fca9595c9f40a666cd36ec1bae50793f9da [file] [log] [blame]
Corentin Wallez3a1746e2020-01-15 13:14:12 +00001// Copyright 2020 the Dawn Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "dawn_native/Surface.h"
16
17#include "common/Platform.h"
Brian Ho5346e772021-04-22 17:49:42 +000018#include "dawn_native/ChainUtils_autogen.h"
Corentin Wallez3a1746e2020-01-15 13:14:12 +000019#include "dawn_native/Instance.h"
Corentin Wallezd26ee852020-01-25 10:05:40 +000020#include "dawn_native/SwapChain.h"
Corentin Wallez3a1746e2020-01-15 13:14:12 +000021
22#if defined(DAWN_PLATFORM_WINDOWS)
陈俊嘉74326fe2021-04-27 16:43:27 +000023# include <windows.ui.core.h>
陈俊嘉11379a32021-06-09 08:44:07 +000024# include <windows.ui.xaml.controls.h>
陈俊嘉74326fe2021-04-27 16:43:27 +000025#endif // defined(DAWN_PLATFORM_WINDOWS)
Corentin Wallez3a1746e2020-01-15 13:14:12 +000026
27#if defined(DAWN_USE_X11)
28# include "common/xlib_with_undefs.h"
29#endif // defined(DAWN_USE_X11)
30
31namespace dawn_native {
32
33#if defined(DAWN_ENABLE_BACKEND_METAL)
34 bool InheritsFromCAMetalLayer(void* obj);
35#endif // defined(DAWN_ENABLE_BACKEND_METAL)
36
37 MaybeError ValidateSurfaceDescriptor(const InstanceBase* instance,
38 const SurfaceDescriptor* descriptor) {
Corentin Wallez3a1746e2020-01-15 13:14:12 +000039 if (descriptor->nextInChain == nullptr) {
40 return DAWN_VALIDATION_ERROR("Surface cannot be created with just the base descriptor");
41 }
42
Brian Ho5346e772021-04-22 17:49:42 +000043 DAWN_TRY(ValidateSingleSType(descriptor->nextInChain,
陈俊嘉74326fe2021-04-27 16:43:27 +000044 wgpu::SType::SurfaceDescriptorFromMetalLayer,
45 wgpu::SType::SurfaceDescriptorFromWindowsHWND,
46 wgpu::SType::SurfaceDescriptorFromWindowsCoreWindow,
陈俊嘉11379a32021-06-09 08:44:07 +000047 wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel,
陈俊嘉74326fe2021-04-27 16:43:27 +000048 wgpu::SType::SurfaceDescriptorFromXlib));
Corentin Wallez3a1746e2020-01-15 13:14:12 +000049
Corentin Wallez3a1746e2020-01-15 13:14:12 +000050#if defined(DAWN_ENABLE_BACKEND_METAL)
Brian Ho5346e772021-04-22 17:49:42 +000051 const SurfaceDescriptorFromMetalLayer* metalDesc = nullptr;
52 FindInChain(descriptor->nextInChain, &metalDesc);
53 if (!metalDesc) {
54 return DAWN_VALIDATION_ERROR("Unsupported sType");
55 }
56 // Check that the layer is a CAMetalLayer (or a derived class).
57 if (!InheritsFromCAMetalLayer(metalDesc->layer)) {
58 return DAWN_VALIDATION_ERROR("layer must be a CAMetalLayer");
59 }
Corentin Wallez3a1746e2020-01-15 13:14:12 +000060#endif // defined(DAWN_ENABLE_BACKEND_METAL)
61
陈俊嘉74326fe2021-04-27 16:43:27 +000062#if defined(DAWN_PLATFORM_WINDOWS)
63# if defined(DAWN_PLATFORM_WIN32)
Brian Ho5346e772021-04-22 17:49:42 +000064 const SurfaceDescriptorFromWindowsHWND* hwndDesc = nullptr;
65 FindInChain(descriptor->nextInChain, &hwndDesc);
陈俊嘉74326fe2021-04-27 16:43:27 +000066 if (hwndDesc) {
67 if (IsWindow(static_cast<HWND>(hwndDesc->hwnd)) == 0) {
68 return DAWN_VALIDATION_ERROR("Invalid HWND");
69 }
70 return {};
Brian Ho5346e772021-04-22 17:49:42 +000071 }
陈俊嘉74326fe2021-04-27 16:43:27 +000072# endif // defined(DAWN_PLATFORM_WIN32)
73 const SurfaceDescriptorFromWindowsCoreWindow* coreWindowDesc = nullptr;
74 FindInChain(descriptor->nextInChain, &coreWindowDesc);
75 if (coreWindowDesc) {
76 // Validate the coreWindow by query for ICoreWindow interface
77 ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
78 if (coreWindowDesc->coreWindow == nullptr ||
79 FAILED(static_cast<IUnknown*>(coreWindowDesc->coreWindow)
80 ->QueryInterface(IID_PPV_ARGS(&coreWindow)))) {
81 return DAWN_VALIDATION_ERROR("Invalid CoreWindow");
82 }
83 return {};
Brian Ho5346e772021-04-22 17:49:42 +000084 }
陈俊嘉11379a32021-06-09 08:44:07 +000085 const SurfaceDescriptorFromWindowsSwapChainPanel* swapChainPanelDesc = nullptr;
86 FindInChain(descriptor->nextInChain, &swapChainPanelDesc);
87 if (swapChainPanelDesc) {
88 // Validate the swapChainPanel by querying for ISwapChainPanel interface
89 ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
90 if (swapChainPanelDesc->swapChainPanel == nullptr ||
91 FAILED(static_cast<IUnknown*>(swapChainPanelDesc->swapChainPanel)
92 ->QueryInterface(IID_PPV_ARGS(&swapChainPanel)))) {
93 return DAWN_VALIDATION_ERROR("Invalid SwapChainPanel");
94 }
95 return {};
96 }
陈俊嘉74326fe2021-04-27 16:43:27 +000097 return DAWN_VALIDATION_ERROR("Unsupported sType");
98#endif // defined(DAWN_PLATFORM_WINDOWS)
Corentin Wallez3a1746e2020-01-15 13:14:12 +000099
100#if defined(DAWN_USE_X11)
Brian Ho5346e772021-04-22 17:49:42 +0000101 const SurfaceDescriptorFromXlib* xDesc = nullptr;
102 FindInChain(descriptor->nextInChain, &xDesc);
103 if (!xDesc) {
104 return DAWN_VALIDATION_ERROR("Unsupported sType");
Corentin Wallez3a1746e2020-01-15 13:14:12 +0000105 }
Brian Ho5346e772021-04-22 17:49:42 +0000106 // Check the validity of the window by calling a getter function on the window that
107 // returns a status code. If the window is bad the call return a status of zero. We
108 // need to set a temporary X11 error handler while doing this because the default
109 // X11 error handler exits the program on any error.
110 XErrorHandler oldErrorHandler =
111 XSetErrorHandler([](Display*, XErrorEvent*) { return 0; });
112 XWindowAttributes attributes;
113 int status = XGetWindowAttributes(reinterpret_cast<Display*>(xDesc->display),
114 xDesc->window, &attributes);
115 XSetErrorHandler(oldErrorHandler);
116
117 if (status == 0) {
118 return DAWN_VALIDATION_ERROR("Invalid X Window");
119 }
120#endif // defined(DAWN_USE_X11)
Corentin Wallez3a1746e2020-01-15 13:14:12 +0000121
122 return {};
123 }
124
125 Surface::Surface(InstanceBase* instance, const SurfaceDescriptor* descriptor)
126 : mInstance(instance) {
127 ASSERT(descriptor->nextInChain != nullptr);
Brian Ho5346e772021-04-22 17:49:42 +0000128 const SurfaceDescriptorFromMetalLayer* metalDesc = nullptr;
129 const SurfaceDescriptorFromWindowsHWND* hwndDesc = nullptr;
陈俊嘉74326fe2021-04-27 16:43:27 +0000130 const SurfaceDescriptorFromWindowsCoreWindow* coreWindowDesc = nullptr;
陈俊嘉11379a32021-06-09 08:44:07 +0000131 const SurfaceDescriptorFromWindowsSwapChainPanel* swapChainPanelDesc = nullptr;
Brian Ho5346e772021-04-22 17:49:42 +0000132 const SurfaceDescriptorFromXlib* xDesc = nullptr;
133 FindInChain(descriptor->nextInChain, &metalDesc);
134 FindInChain(descriptor->nextInChain, &hwndDesc);
陈俊嘉74326fe2021-04-27 16:43:27 +0000135 FindInChain(descriptor->nextInChain, &coreWindowDesc);
陈俊嘉11379a32021-06-09 08:44:07 +0000136 FindInChain(descriptor->nextInChain, &swapChainPanelDesc);
Brian Ho5346e772021-04-22 17:49:42 +0000137 FindInChain(descriptor->nextInChain, &xDesc);
138 ASSERT(metalDesc || hwndDesc || xDesc);
139 if (metalDesc) {
140 mType = Type::MetalLayer;
141 mMetalLayer = metalDesc->layer;
142 } else if (hwndDesc) {
143 mType = Type::WindowsHWND;
144 mHInstance = hwndDesc->hinstance;
145 mHWND = hwndDesc->hwnd;
陈俊嘉74326fe2021-04-27 16:43:27 +0000146 } else if (coreWindowDesc) {
147#if defined(DAWN_PLATFORM_WINDOWS)
148 mType = Type::WindowsCoreWindow;
149 mCoreWindow = static_cast<IUnknown*>(coreWindowDesc->coreWindow);
150#endif // defined(DAWN_PLATFORM_WINDOWS)
陈俊嘉11379a32021-06-09 08:44:07 +0000151 } else if (swapChainPanelDesc) {
152#if defined(DAWN_PLATFORM_WINDOWS)
153 mType = Type::WindowsSwapChainPanel;
154 mSwapChainPanel = static_cast<IUnknown*>(swapChainPanelDesc->swapChainPanel);
155#endif // defined(DAWN_PLATFORM_WINDOWS)
Brian Ho5346e772021-04-22 17:49:42 +0000156 } else if (xDesc) {
157 mType = Type::Xlib;
158 mXDisplay = xDesc->display;
159 mXWindow = xDesc->window;
陈俊嘉74326fe2021-04-27 16:43:27 +0000160 } else {
161 UNREACHABLE();
Corentin Wallez3a1746e2020-01-15 13:14:12 +0000162 }
163 }
164
Corentin Wallezd26ee852020-01-25 10:05:40 +0000165 Surface::~Surface() {
166 if (mSwapChain != nullptr) {
167 mSwapChain->DetachFromSurface();
168 mSwapChain = nullptr;
169 }
170 }
171
Corentin Wallez25eeaa32020-10-27 11:31:26 +0000172 NewSwapChainBase* Surface::GetAttachedSwapChain() {
173 return mSwapChain.Get();
Corentin Wallezd26ee852020-01-25 10:05:40 +0000174 }
175
176 void Surface::SetAttachedSwapChain(NewSwapChainBase* swapChain) {
177 mSwapChain = swapChain;
178 }
Corentin Wallez3a1746e2020-01-15 13:14:12 +0000179
180 InstanceBase* Surface::GetInstance() {
181 return mInstance.Get();
182 }
183
184 Surface::Type Surface::GetType() const {
185 return mType;
186 }
187
188 void* Surface::GetMetalLayer() const {
189 ASSERT(mType == Type::MetalLayer);
190 return mMetalLayer;
191 }
192
193 void* Surface::GetHInstance() const {
194 ASSERT(mType == Type::WindowsHWND);
195 return mHInstance;
196 }
197 void* Surface::GetHWND() const {
198 ASSERT(mType == Type::WindowsHWND);
199 return mHWND;
200 }
201
陈俊嘉e7a5fab2021-05-06 08:28:44 +0000202 IUnknown* Surface::GetCoreWindow() const {
陈俊嘉74326fe2021-04-27 16:43:27 +0000203 ASSERT(mType == Type::WindowsCoreWindow);
204#if defined(DAWN_PLATFORM_WINDOWS)
205 return mCoreWindow.Get();
206#else
207 return nullptr;
208#endif
209 }
210
陈俊嘉11379a32021-06-09 08:44:07 +0000211 IUnknown* Surface::GetSwapChainPanel() const {
212 ASSERT(mType == Type::WindowsSwapChainPanel);
213#if defined(DAWN_PLATFORM_WINDOWS)
214 return mSwapChainPanel.Get();
215#else
216 return nullptr;
217#endif
218 }
219
Corentin Wallez3a1746e2020-01-15 13:14:12 +0000220 void* Surface::GetXDisplay() const {
221 ASSERT(mType == Type::Xlib);
222 return mXDisplay;
223 }
224 uint32_t Surface::GetXWindow() const {
225 ASSERT(mType == Type::Xlib);
226 return mXWindow;
227 }
228
229} // namespace dawn_native