• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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"
18 #include "dawn_native/ChainUtils_autogen.h"
19 #include "dawn_native/Instance.h"
20 #include "dawn_native/SwapChain.h"
21 
22 #if defined(DAWN_PLATFORM_WINDOWS)
23 #    include <windows.ui.core.h>
24 #    include <windows.ui.xaml.controls.h>
25 #endif  // defined(DAWN_PLATFORM_WINDOWS)
26 
27 #if defined(DAWN_USE_X11)
28 #    include "common/xlib_with_undefs.h"
29 #endif  // defined(DAWN_USE_X11)
30 
31 namespace dawn_native {
32 
AbslFormatConvert(Surface::Type value,const absl::FormatConversionSpec & spec,absl::FormatSink * s)33     absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
34         Surface::Type value,
35         const absl::FormatConversionSpec& spec,
36         absl::FormatSink* s) {
37         switch (value) {
38             case Surface::Type::MetalLayer:
39                 s->Append("MetalLayer");
40                 break;
41             case Surface::Type::WindowsHWND:
42                 s->Append("WindowsHWND");
43                 break;
44             case Surface::Type::WindowsCoreWindow:
45                 s->Append("WindowsCoreWindow");
46                 break;
47             case Surface::Type::WindowsSwapChainPanel:
48                 s->Append("WindowsSwapChainPanel");
49                 break;
50             case Surface::Type::Xlib:
51                 s->Append("Xlib");
52                 break;
53         }
54         return {true};
55     }
56 
57 #if defined(DAWN_ENABLE_BACKEND_METAL)
58     bool InheritsFromCAMetalLayer(void* obj);
59 #endif  // defined(DAWN_ENABLE_BACKEND_METAL)
60 
ValidateSurfaceDescriptor(const InstanceBase * instance,const SurfaceDescriptor * descriptor)61     MaybeError ValidateSurfaceDescriptor(const InstanceBase* instance,
62                                          const SurfaceDescriptor* descriptor) {
63         DAWN_INVALID_IF(descriptor->nextInChain == nullptr,
64                         "Surface cannot be created with %s. nextInChain is not specified.",
65                         descriptor);
66 
67         DAWN_TRY(ValidateSingleSType(descriptor->nextInChain,
68                                      wgpu::SType::SurfaceDescriptorFromMetalLayer,
69                                      wgpu::SType::SurfaceDescriptorFromWindowsHWND,
70                                      wgpu::SType::SurfaceDescriptorFromWindowsCoreWindow,
71                                      wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel,
72                                      wgpu::SType::SurfaceDescriptorFromXlib));
73 
74 #if defined(DAWN_ENABLE_BACKEND_METAL)
75         const SurfaceDescriptorFromMetalLayer* metalDesc = nullptr;
76         FindInChain(descriptor->nextInChain, &metalDesc);
77         if (metalDesc) {
78             // Check that the layer is a CAMetalLayer (or a derived class).
79             DAWN_INVALID_IF(!InheritsFromCAMetalLayer(metalDesc->layer),
80                             "Layer must be a CAMetalLayer");
81             return {};
82         }
83 #endif  // defined(DAWN_ENABLE_BACKEND_METAL)
84 
85 #if defined(DAWN_PLATFORM_WINDOWS)
86 #    if defined(DAWN_PLATFORM_WIN32)
87         const SurfaceDescriptorFromWindowsHWND* hwndDesc = nullptr;
88         FindInChain(descriptor->nextInChain, &hwndDesc);
89         if (hwndDesc) {
90             DAWN_INVALID_IF(IsWindow(static_cast<HWND>(hwndDesc->hwnd)) == 0, "Invalid HWND");
91             return {};
92         }
93 #    endif  // defined(DAWN_PLATFORM_WIN32)
94         const SurfaceDescriptorFromWindowsCoreWindow* coreWindowDesc = nullptr;
95         FindInChain(descriptor->nextInChain, &coreWindowDesc);
96         if (coreWindowDesc) {
97             // Validate the coreWindow by query for ICoreWindow interface
98             ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
99             DAWN_INVALID_IF(coreWindowDesc->coreWindow == nullptr ||
100                                 FAILED(static_cast<IUnknown*>(coreWindowDesc->coreWindow)
101                                            ->QueryInterface(IID_PPV_ARGS(&coreWindow))),
102                             "Invalid CoreWindow");
103             return {};
104         }
105         const SurfaceDescriptorFromWindowsSwapChainPanel* swapChainPanelDesc = nullptr;
106         FindInChain(descriptor->nextInChain, &swapChainPanelDesc);
107         if (swapChainPanelDesc) {
108             // Validate the swapChainPanel by querying for ISwapChainPanel interface
109             ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
110             DAWN_INVALID_IF(swapChainPanelDesc->swapChainPanel == nullptr ||
111                                 FAILED(static_cast<IUnknown*>(swapChainPanelDesc->swapChainPanel)
112                                            ->QueryInterface(IID_PPV_ARGS(&swapChainPanel))),
113                             "Invalid SwapChainPanel");
114             return {};
115         }
116 #endif  // defined(DAWN_PLATFORM_WINDOWS)
117 
118 #if defined(DAWN_USE_X11)
119         const SurfaceDescriptorFromXlib* xDesc = nullptr;
120         FindInChain(descriptor->nextInChain, &xDesc);
121         if (xDesc) {
122             // Check the validity of the window by calling a getter function on the window that
123             // returns a status code. If the window is bad the call return a status of zero. We
124             // need to set a temporary X11 error handler while doing this because the default
125             // X11 error handler exits the program on any error.
126             XErrorHandler oldErrorHandler =
127                 XSetErrorHandler([](Display*, XErrorEvent*) { return 0; });
128             XWindowAttributes attributes;
129             int status = XGetWindowAttributes(reinterpret_cast<Display*>(xDesc->display),
130                                               xDesc->window, &attributes);
131             XSetErrorHandler(oldErrorHandler);
132 
133             DAWN_INVALID_IF(status == 0, "Invalid X Window");
134             return {};
135         }
136 #endif  // defined(DAWN_USE_X11)
137 
138         return DAWN_FORMAT_VALIDATION_ERROR("Unsupported sType (%s)",
139                                             descriptor->nextInChain->sType);
140     }
141 
Surface(InstanceBase * instance,const SurfaceDescriptor * descriptor)142     Surface::Surface(InstanceBase* instance, const SurfaceDescriptor* descriptor)
143         : mInstance(instance) {
144         ASSERT(descriptor->nextInChain != nullptr);
145         const SurfaceDescriptorFromMetalLayer* metalDesc = nullptr;
146         const SurfaceDescriptorFromWindowsHWND* hwndDesc = nullptr;
147         const SurfaceDescriptorFromWindowsCoreWindow* coreWindowDesc = nullptr;
148         const SurfaceDescriptorFromWindowsSwapChainPanel* swapChainPanelDesc = nullptr;
149         const SurfaceDescriptorFromXlib* xDesc = nullptr;
150         FindInChain(descriptor->nextInChain, &metalDesc);
151         FindInChain(descriptor->nextInChain, &hwndDesc);
152         FindInChain(descriptor->nextInChain, &coreWindowDesc);
153         FindInChain(descriptor->nextInChain, &swapChainPanelDesc);
154         FindInChain(descriptor->nextInChain, &xDesc);
155         ASSERT(metalDesc || hwndDesc || xDesc);
156         if (metalDesc) {
157             mType = Type::MetalLayer;
158             mMetalLayer = metalDesc->layer;
159         } else if (hwndDesc) {
160             mType = Type::WindowsHWND;
161             mHInstance = hwndDesc->hinstance;
162             mHWND = hwndDesc->hwnd;
163         } else if (coreWindowDesc) {
164 #if defined(DAWN_PLATFORM_WINDOWS)
165             mType = Type::WindowsCoreWindow;
166             mCoreWindow = static_cast<IUnknown*>(coreWindowDesc->coreWindow);
167 #endif  // defined(DAWN_PLATFORM_WINDOWS)
168         } else if (swapChainPanelDesc) {
169 #if defined(DAWN_PLATFORM_WINDOWS)
170             mType = Type::WindowsSwapChainPanel;
171             mSwapChainPanel = static_cast<IUnknown*>(swapChainPanelDesc->swapChainPanel);
172 #endif  // defined(DAWN_PLATFORM_WINDOWS)
173         } else if (xDesc) {
174             mType = Type::Xlib;
175             mXDisplay = xDesc->display;
176             mXWindow = xDesc->window;
177         } else {
178             UNREACHABLE();
179         }
180     }
181 
~Surface()182     Surface::~Surface() {
183         if (mSwapChain != nullptr) {
184             mSwapChain->DetachFromSurface();
185             mSwapChain = nullptr;
186         }
187     }
188 
GetAttachedSwapChain()189     NewSwapChainBase* Surface::GetAttachedSwapChain() {
190         return mSwapChain.Get();
191     }
192 
SetAttachedSwapChain(NewSwapChainBase * swapChain)193     void Surface::SetAttachedSwapChain(NewSwapChainBase* swapChain) {
194         mSwapChain = swapChain;
195     }
196 
GetInstance()197     InstanceBase* Surface::GetInstance() {
198         return mInstance.Get();
199     }
200 
GetType() const201     Surface::Type Surface::GetType() const {
202         return mType;
203     }
204 
GetMetalLayer() const205     void* Surface::GetMetalLayer() const {
206         ASSERT(mType == Type::MetalLayer);
207         return mMetalLayer;
208     }
209 
GetHInstance() const210     void* Surface::GetHInstance() const {
211         ASSERT(mType == Type::WindowsHWND);
212         return mHInstance;
213     }
GetHWND() const214     void* Surface::GetHWND() const {
215         ASSERT(mType == Type::WindowsHWND);
216         return mHWND;
217     }
218 
GetCoreWindow() const219     IUnknown* Surface::GetCoreWindow() const {
220         ASSERT(mType == Type::WindowsCoreWindow);
221 #if defined(DAWN_PLATFORM_WINDOWS)
222         return mCoreWindow.Get();
223 #else
224         return nullptr;
225 #endif
226     }
227 
GetSwapChainPanel() const228     IUnknown* Surface::GetSwapChainPanel() const {
229         ASSERT(mType == Type::WindowsSwapChainPanel);
230 #if defined(DAWN_PLATFORM_WINDOWS)
231         return mSwapChainPanel.Get();
232 #else
233         return nullptr;
234 #endif
235     }
236 
GetXDisplay() const237     void* Surface::GetXDisplay() const {
238         ASSERT(mType == Type::Xlib);
239         return mXDisplay;
240     }
GetXWindow() const241     uint32_t Surface::GetXWindow() const {
242         ASSERT(mType == Type::Xlib);
243         return mXWindow;
244     }
245 
246 }  // namespace dawn_native
247