• 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 "common/Log.h"
16 #include "common/Platform.h"
17 #include "dawn/dawn_proc.h"
18 #include "dawn_native/DawnNative.h"
19 #include "tests/DawnTest.h"
20 #include "utils/GLFWUtils.h"
21 
22 #include <gtest/gtest.h>
23 
24 #include <cstdlib>
25 
26 // Include windows.h before GLFW so GLFW's APIENTRY macro doesn't conflict with windows.h's.
27 #if defined(DAWN_PLATFORM_WINDOWS)
28 #    include "common/windows_with_undefs.h"
29 #endif  // defined(DAWN_PLATFORM_WINDOWS)
30 
31 #include "GLFW/glfw3.h"
32 
33 #if defined(DAWN_USE_X11)
34 #    include "common/xlib_with_undefs.h"
35 #endif  // defined(DAWN_USE_X11)
36 
37 #if defined(DAWN_ENABLE_BACKEND_METAL)
38 #    include "utils/ObjCUtils.h"
39 #endif  // defined(DAWN_ENABLE_BACKEND_METAL)
40 
41 #include "GLFW/glfw3native.h"
42 
43 // Test for wgpu::Surface creation that only need an instance (no devices) and don't need all the
44 // complexity of DawnTest.
45 class WindowSurfaceInstanceTests : public testing::Test {
46   public:
SetUp()47     void SetUp() override {
48         glfwSetErrorCallback([](int code, const char* message) {
49             dawn::ErrorLog() << "GLFW error " << code << " " << message;
50         });
51         DAWN_TEST_UNSUPPORTED_IF(!glfwInit());
52 
53         dawnProcSetProcs(&dawn_native::GetProcs());
54 
55         mInstance = wgpu::CreateInstance();
56     }
57 
TearDown()58     void TearDown() override {
59         if (mWindow != nullptr) {
60             glfwDestroyWindow(mWindow);
61             mWindow = nullptr;
62         }
63     }
64 
AssertSurfaceCreation(const wgpu::SurfaceDescriptor * descriptor,bool succeeds)65     void AssertSurfaceCreation(const wgpu::SurfaceDescriptor* descriptor, bool succeeds) {
66         ASSERT_EQ(mInstance.CreateSurface(descriptor).Get() != nullptr, succeeds);
67     }
68 
CreateWindow()69     GLFWwindow* CreateWindow() {
70         // The WindowSurfaceInstance tests don't create devices so we don't need to call
71         // SetupGLFWWindowHintsForBackend. Set GLFW_NO_API anyway to avoid GLFW bringing up a GL
72         // context that we won't use.
73         glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
74         mWindow = glfwCreateWindow(400, 400, "WindowSurfaceInstanceTests window", nullptr, nullptr);
75         return mWindow;
76     }
77 
78   private:
79     wgpu::Instance mInstance;
80     GLFWwindow* mWindow = nullptr;
81 };
82 
83 // Test that a valid chained descriptor works (and that GLFWUtils creates a valid chained
84 // descriptor).
TEST_F(WindowSurfaceInstanceTests,ControlCase)85 TEST_F(WindowSurfaceInstanceTests, ControlCase) {
86     GLFWwindow* window = CreateWindow();
87     std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
88         utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
89 
90     wgpu::SurfaceDescriptor descriptor;
91     descriptor.nextInChain = chainedDescriptor.get();
92 
93     AssertSurfaceCreation(&descriptor, true);
94 }
95 
96 // Test that just wgpu::SurfaceDescriptor isn't enough and needs a chained descriptor.
TEST_F(WindowSurfaceInstanceTests,NoChainedDescriptors)97 TEST_F(WindowSurfaceInstanceTests, NoChainedDescriptors) {
98     wgpu::SurfaceDescriptor descriptor;
99     descriptor.nextInChain = nullptr;  // That's the default value but we set it for clarity.
100 
101     AssertSurfaceCreation(&descriptor, false);
102 }
103 
104 // Test that a chained descriptor with a garbage sType produces an error.
TEST_F(WindowSurfaceInstanceTests,BadChainedDescriptors)105 TEST_F(WindowSurfaceInstanceTests, BadChainedDescriptors) {
106     wgpu::ChainedStruct chainedDescriptor;
107     chainedDescriptor.sType = wgpu::SType::Invalid;  // The default but we set it for clarity.
108 
109     wgpu::SurfaceDescriptor descriptor;
110     descriptor.nextInChain = &chainedDescriptor;
111 
112     AssertSurfaceCreation(&descriptor, false);
113 }
114 
115 // Test that a chained descriptor with HTMLCanvas produces an error.
TEST_F(WindowSurfaceInstanceTests,HTMLCanvasDescriptor)116 TEST_F(WindowSurfaceInstanceTests, HTMLCanvasDescriptor) {
117     wgpu::SurfaceDescriptorFromCanvasHTMLSelector chainedDescriptor;
118     chainedDescriptor.selector = "#myCanvas";
119 
120     wgpu::SurfaceDescriptor descriptor;
121     descriptor.nextInChain = &chainedDescriptor;
122 
123     AssertSurfaceCreation(&descriptor, false);
124 }
125 
126 // Test that it is invalid to give two valid chained descriptors
TEST_F(WindowSurfaceInstanceTests,TwoChainedDescriptors)127 TEST_F(WindowSurfaceInstanceTests, TwoChainedDescriptors) {
128     GLFWwindow* window = CreateWindow();
129     std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor1 =
130         utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
131     std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor2 =
132         utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
133 
134     wgpu::SurfaceDescriptor descriptor;
135     descriptor.nextInChain = chainedDescriptor1.get();
136     chainedDescriptor1->nextInChain = chainedDescriptor2.get();
137 
138     AssertSurfaceCreation(&descriptor, false);
139 }
140 
141 #if defined(DAWN_PLATFORM_WINDOWS)
142 
143 // Tests that GLFWUtils returns a descriptor of HWND type
TEST_F(WindowSurfaceInstanceTests,CorrectSTypeHWND)144 TEST_F(WindowSurfaceInstanceTests, CorrectSTypeHWND) {
145     GLFWwindow* window = CreateWindow();
146     std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
147         utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
148     ASSERT_EQ(chainedDescriptor->sType, wgpu::SType::SurfaceDescriptorFromWindowsHWND);
149 }
150 
151 // Test with setting an invalid hwnd
TEST_F(WindowSurfaceInstanceTests,InvalidHWND)152 TEST_F(WindowSurfaceInstanceTests, InvalidHWND) {
153     wgpu::SurfaceDescriptorFromWindowsHWND chainedDescriptor;
154     chainedDescriptor.hinstance = GetModuleHandle(nullptr);
155     chainedDescriptor.hwnd = 0;  // This always is an invalid HWND value.
156 
157     wgpu::SurfaceDescriptor descriptor;
158     descriptor.nextInChain = &chainedDescriptor;
159     AssertSurfaceCreation(&descriptor, false);
160 }
161 
162 #else  // defined(DAWN_PLATFORM_WINDOWS)
163 
164 // Test using HWND when it is not supported
TEST_F(WindowSurfaceInstanceTests,HWNDSurfacesAreInvalid)165 TEST_F(WindowSurfaceInstanceTests, HWNDSurfacesAreInvalid) {
166     wgpu::SurfaceDescriptorFromWindowsHWND chainedDescriptor;
167     chainedDescriptor.hinstance = nullptr;
168     chainedDescriptor.hwnd = 0;
169 
170     wgpu::SurfaceDescriptor descriptor;
171     descriptor.nextInChain = &chainedDescriptor;
172     AssertSurfaceCreation(&descriptor, false);
173 }
174 
175 #endif  // defined(DAWN_PLATFORM_WINDOWS)
176 
177 #if defined(DAWN_USE_X11)
178 
179 // Tests that GLFWUtils returns a descriptor of Xlib type
TEST_F(WindowSurfaceInstanceTests,CorrectSTypeXlib)180 TEST_F(WindowSurfaceInstanceTests, CorrectSTypeXlib) {
181     GLFWwindow* window = CreateWindow();
182     std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
183         utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
184     ASSERT_EQ(chainedDescriptor->sType, wgpu::SType::SurfaceDescriptorFromXlib);
185 }
186 
187 // Test with setting an invalid window
TEST_F(WindowSurfaceInstanceTests,InvalidXWindow)188 TEST_F(WindowSurfaceInstanceTests, InvalidXWindow) {
189     wgpu::SurfaceDescriptorFromXlib chainedDescriptor;
190     chainedDescriptor.display = XOpenDisplay(nullptr);
191     // From the "X Window System Protocol" "X Version 11, Release 6.8" page 2 at
192     // https://www.x.org/releases/X11R7.5/doc/x11proto/proto.pdf
193     //    WINDOW 32-bit value (top three bits guaranteed to be zero.
194     // So UINT32_MAX should be an invalid window.
195     chainedDescriptor.window = 0xFFFFFFFF;
196 
197     wgpu::SurfaceDescriptor descriptor;
198     descriptor.nextInChain = &chainedDescriptor;
199     AssertSurfaceCreation(&descriptor, false);
200 }
201 
202 #else  // defined(DAWN_USE_X11)
203 
204 // Test using Xlib when it is not supported
TEST_F(WindowSurfaceInstanceTests,XlibSurfacesAreInvalid)205 TEST_F(WindowSurfaceInstanceTests, XlibSurfacesAreInvalid) {
206     wgpu::SurfaceDescriptorFromXlib chainedDescriptor;
207     chainedDescriptor.display = nullptr;
208     chainedDescriptor.window = 0;
209 
210     wgpu::SurfaceDescriptor descriptor;
211     descriptor.nextInChain = &chainedDescriptor;
212     AssertSurfaceCreation(&descriptor, false);
213 }
214 
215 #endif  // defined(DAWN_USE_X11)
216 
217 #if defined(DAWN_ENABLE_BACKEND_METAL)
218 
219 // Tests that GLFWUtils returns a descriptor of Metal type
TEST_F(WindowSurfaceInstanceTests,CorrectSTypeMetal)220 TEST_F(WindowSurfaceInstanceTests, CorrectSTypeMetal) {
221     GLFWwindow* window = CreateWindow();
222     std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
223         utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
224     ASSERT_EQ(chainedDescriptor->sType, wgpu::SType::SurfaceDescriptorFromMetalLayer);
225 }
226 
227 // Test with setting an invalid layer
TEST_F(WindowSurfaceInstanceTests,InvalidMetalLayer)228 TEST_F(WindowSurfaceInstanceTests, InvalidMetalLayer) {
229     wgpu::SurfaceDescriptorFromMetalLayer chainedDescriptor;
230     // The CALayer is autoreleased. Releasing it causes a test failure when the Chromium GTest
231     // autoreleasepool is emptied.
232     chainedDescriptor.layer = utils::CreateDummyCALayer();
233 
234     wgpu::SurfaceDescriptor descriptor;
235     descriptor.nextInChain = &chainedDescriptor;
236     AssertSurfaceCreation(&descriptor, false);
237 }
238 
239 #else  // defined(DAWN_ENABLE_BACKEND_METAL)
240 
241 // Test using Metal when it is not supported
TEST_F(WindowSurfaceInstanceTests,MetalSurfacesAreInvalid)242 TEST_F(WindowSurfaceInstanceTests, MetalSurfacesAreInvalid) {
243     wgpu::SurfaceDescriptorFromMetalLayer chainedDescriptor;
244     chainedDescriptor.layer = nullptr;
245 
246     wgpu::SurfaceDescriptor descriptor;
247     descriptor.nextInChain = &chainedDescriptor;
248     AssertSurfaceCreation(&descriptor, false);
249 }
250 
251 #endif  // defined(DAWN_ENABLE_BACKEND_METAL)
252