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 // DisplayWgpu.cpp:
7 // Implements the class methods for DisplayWgpu.
8 //
9
10 #include "libANGLE/renderer/wgpu/DisplayWgpu.h"
11
12 #include <dawn/dawn_proc.h>
13
14 #include "common/debug.h"
15 #include "common/platform.h"
16
17 #include "libANGLE/Display.h"
18 #include "libANGLE/renderer/wgpu/ContextWgpu.h"
19 #include "libANGLE/renderer/wgpu/DeviceWgpu.h"
20 #include "libANGLE/renderer/wgpu/DisplayWgpu_api.h"
21 #include "libANGLE/renderer/wgpu/ImageWgpu.h"
22 #include "libANGLE/renderer/wgpu/SurfaceWgpu.h"
23
24 namespace rx
25 {
26
DisplayWgpu(const egl::DisplayState & state)27 DisplayWgpu::DisplayWgpu(const egl::DisplayState &state) : DisplayImpl(state) {}
28
~DisplayWgpu()29 DisplayWgpu::~DisplayWgpu() {}
30
initialize(egl::Display * display)31 egl::Error DisplayWgpu::initialize(egl::Display *display)
32 {
33 ANGLE_TRY(createWgpuDevice());
34
35 mQueue = mDevice.GetQueue();
36 mFormatTable.initialize();
37
38 mDevice.GetLimits(&mLimitsWgpu);
39
40 webgpu::GenerateCaps(mLimitsWgpu, &mGLCaps, &mGLTextureCaps, &mGLExtensions, &mGLLimitations,
41 &mEGLCaps, &mEGLExtensions, &mMaxSupportedClientVersion);
42
43 return egl::NoError();
44 }
45
terminate()46 void DisplayWgpu::terminate() {}
47
makeCurrent(egl::Display * display,egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)48 egl::Error DisplayWgpu::makeCurrent(egl::Display *display,
49 egl::Surface *drawSurface,
50 egl::Surface *readSurface,
51 gl::Context *context)
52 {
53 // Ensure that the correct global DebugAnnotator is installed when the end2end tests change
54 // the ANGLE back-end (done frequently).
55 display->setGlobalDebugAnnotator();
56
57 return egl::NoError();
58 }
59
generateConfigs()60 egl::ConfigSet DisplayWgpu::generateConfigs()
61 {
62 egl::Config config;
63 config.renderTargetFormat = GL_BGRA8_EXT;
64 config.depthStencilFormat = GL_DEPTH24_STENCIL8;
65 config.bufferSize = 32;
66 config.redSize = 8;
67 config.greenSize = 8;
68 config.blueSize = 8;
69 config.alphaSize = 8;
70 config.alphaMaskSize = 0;
71 config.bindToTextureRGB = EGL_TRUE;
72 config.bindToTextureRGBA = EGL_TRUE;
73 config.colorBufferType = EGL_RGB_BUFFER;
74 config.configCaveat = EGL_NONE;
75 config.conformant = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
76 config.depthSize = 24;
77 config.level = 0;
78 config.matchNativePixmap = EGL_NONE;
79 config.maxPBufferWidth = 0;
80 config.maxPBufferHeight = 0;
81 config.maxPBufferPixels = 0;
82 config.maxSwapInterval = 1;
83 config.minSwapInterval = 1;
84 config.nativeRenderable = EGL_TRUE;
85 config.nativeVisualID = 0;
86 config.nativeVisualType = EGL_NONE;
87 config.renderableType = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
88 config.sampleBuffers = 0;
89 config.samples = 0;
90 config.stencilSize = 8;
91 config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
92 config.optimalOrientation = 0;
93 config.transparentType = EGL_NONE;
94 config.transparentRedValue = 0;
95 config.transparentGreenValue = 0;
96 config.transparentBlueValue = 0;
97
98 egl::ConfigSet configSet;
99 configSet.add(config);
100 return configSet;
101 }
102
testDeviceLost()103 bool DisplayWgpu::testDeviceLost()
104 {
105 return false;
106 }
107
restoreLostDevice(const egl::Display * display)108 egl::Error DisplayWgpu::restoreLostDevice(const egl::Display *display)
109 {
110 return egl::NoError();
111 }
112
isValidNativeWindow(EGLNativeWindowType window) const113 bool DisplayWgpu::isValidNativeWindow(EGLNativeWindowType window) const
114 {
115 return true;
116 }
117
getRendererDescription()118 std::string DisplayWgpu::getRendererDescription()
119 {
120 return "Wgpu";
121 }
122
getVendorString()123 std::string DisplayWgpu::getVendorString()
124 {
125 return "Wgpu";
126 }
127
getVersionString(bool includeFullVersion)128 std::string DisplayWgpu::getVersionString(bool includeFullVersion)
129 {
130 return std::string();
131 }
132
createDevice()133 DeviceImpl *DisplayWgpu::createDevice()
134 {
135 return new DeviceWgpu();
136 }
137
waitClient(const gl::Context * context)138 egl::Error DisplayWgpu::waitClient(const gl::Context *context)
139 {
140 return egl::NoError();
141 }
142
waitNative(const gl::Context * context,EGLint engine)143 egl::Error DisplayWgpu::waitNative(const gl::Context *context, EGLint engine)
144 {
145 return egl::NoError();
146 }
147
getMaxSupportedESVersion() const148 gl::Version DisplayWgpu::getMaxSupportedESVersion() const
149 {
150 return mMaxSupportedClientVersion;
151 }
152
getMaxConformantESVersion() const153 gl::Version DisplayWgpu::getMaxConformantESVersion() const
154 {
155 return mMaxSupportedClientVersion;
156 }
157
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)158 SurfaceImpl *DisplayWgpu::createWindowSurface(const egl::SurfaceState &state,
159 EGLNativeWindowType window,
160 const egl::AttributeMap &attribs)
161 {
162 return CreateWgpuWindowSurface(state, window);
163 }
164
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)165 SurfaceImpl *DisplayWgpu::createPbufferSurface(const egl::SurfaceState &state,
166 const egl::AttributeMap &attribs)
167 {
168 return new OffscreenSurfaceWgpu(state);
169 }
170
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer buffer,const egl::AttributeMap & attribs)171 SurfaceImpl *DisplayWgpu::createPbufferFromClientBuffer(const egl::SurfaceState &state,
172 EGLenum buftype,
173 EGLClientBuffer buffer,
174 const egl::AttributeMap &attribs)
175 {
176 UNIMPLEMENTED();
177 return nullptr;
178 }
179
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)180 SurfaceImpl *DisplayWgpu::createPixmapSurface(const egl::SurfaceState &state,
181 NativePixmapType nativePixmap,
182 const egl::AttributeMap &attribs)
183 {
184 UNIMPLEMENTED();
185 return nullptr;
186 }
187
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)188 ImageImpl *DisplayWgpu::createImage(const egl::ImageState &state,
189 const gl::Context *context,
190 EGLenum target,
191 const egl::AttributeMap &attribs)
192 {
193 return new ImageWgpu(state);
194 }
195
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)196 rx::ContextImpl *DisplayWgpu::createContext(const gl::State &state,
197 gl::ErrorSet *errorSet,
198 const egl::Config *configuration,
199 const gl::Context *shareContext,
200 const egl::AttributeMap &attribs)
201 {
202 return new ContextWgpu(state, errorSet, this);
203 }
204
createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)205 StreamProducerImpl *DisplayWgpu::createStreamProducerD3DTexture(
206 egl::Stream::ConsumerType consumerType,
207 const egl::AttributeMap &attribs)
208 {
209 UNIMPLEMENTED();
210 return nullptr;
211 }
212
createShareGroup(const egl::ShareGroupState & state)213 ShareGroupImpl *DisplayWgpu::createShareGroup(const egl::ShareGroupState &state)
214 {
215 return new ShareGroupWgpu(state);
216 }
217
getWindowSystem() const218 angle::NativeWindowSystem DisplayWgpu::getWindowSystem() const
219 {
220 #if defined(ANGLE_PLATFORM_LINUX)
221 # if defined(ANGLE_USE_X11)
222 return angle::NativeWindowSystem::X11;
223 # elif defined(ANGLE_USE_WAYLAND)
224 return angle::NativeWindowSystem::Wayland;
225 # endif
226 #else
227 return angle::NativeWindowSystem::Other;
228 #endif
229 }
230
generateExtensions(egl::DisplayExtensions * outExtensions) const231 void DisplayWgpu::generateExtensions(egl::DisplayExtensions *outExtensions) const
232 {
233 *outExtensions = mEGLExtensions;
234 }
235
generateCaps(egl::Caps * outCaps) const236 void DisplayWgpu::generateCaps(egl::Caps *outCaps) const
237 {
238 *outCaps = mEGLCaps;
239 }
240
createWgpuDevice()241 egl::Error DisplayWgpu::createWgpuDevice()
242 {
243 dawnProcSetProcs(&dawn::native::GetProcs());
244
245 dawn::native::DawnInstanceDescriptor dawnInstanceDescriptor;
246
247 wgpu::InstanceDescriptor instanceDescriptor;
248 instanceDescriptor.capabilities.timedWaitAnyEnable = true;
249 instanceDescriptor.nextInChain = &dawnInstanceDescriptor;
250 mInstance = wgpu::CreateInstance(&instanceDescriptor);
251
252 struct RequestAdapterResult
253 {
254 wgpu::RequestAdapterStatus status;
255 wgpu::Adapter adapter;
256 std::string message;
257 };
258 RequestAdapterResult adapterResult;
259
260 wgpu::RequestAdapterOptions requestAdapterOptions;
261
262 wgpu::RequestAdapterCallback<RequestAdapterResult *> *requestAdapterCallback =
263 [](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message,
264 RequestAdapterResult *result) {
265 result->status = status;
266 result->adapter = adapter;
267 result->message = message;
268 };
269 wgpu::FutureWaitInfo futureWaitInfo;
270 futureWaitInfo.future =
271 mInstance.RequestAdapter(&requestAdapterOptions, wgpu::CallbackMode::WaitAnyOnly,
272 requestAdapterCallback, &adapterResult);
273
274 wgpu::WaitStatus status = mInstance.WaitAny(1, &futureWaitInfo, -1);
275 if (webgpu::IsWgpuError(status))
276 {
277 std::ostringstream err;
278 err << "Failed to get WebGPU adapter: " << adapterResult.message;
279 return egl::Error(EGL_BAD_ALLOC, err.str());
280 }
281
282 mAdapter = adapterResult.adapter;
283
284 std::vector<wgpu::FeatureName> requiredFeatures; // empty for now
285
286 wgpu::DeviceDescriptor deviceDesc;
287 deviceDesc.requiredFeatureCount = requiredFeatures.size();
288 deviceDesc.requiredFeatures = requiredFeatures.data();
289 deviceDesc.SetUncapturedErrorCallback(
290 [](const wgpu::Device &device, wgpu::ErrorType type, wgpu::StringView message) {
291 ERR() << "Error: " << static_cast<std::underlying_type<wgpu::ErrorType>::type>(type)
292 << " - message: " << std::string(message);
293 });
294
295 mDevice = mAdapter.CreateDevice(&deviceDesc);
296 return egl::NoError();
297 }
298
CreateWgpuDisplay(const egl::DisplayState & state)299 DisplayImpl *CreateWgpuDisplay(const egl::DisplayState &state)
300 {
301 return new DisplayWgpu(state);
302 }
303
304 } // namespace rx
305