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
16 #include "libANGLE/Display.h"
17 #include "libANGLE/renderer/wgpu/ContextWgpu.h"
18 #include "libANGLE/renderer/wgpu/DeviceWgpu.h"
19 #include "libANGLE/renderer/wgpu/DisplayWgpu_api.h"
20 #include "libANGLE/renderer/wgpu/ImageWgpu.h"
21 #include "libANGLE/renderer/wgpu/SurfaceWgpu.h"
22
23 namespace rx
24 {
25
26 static wgpu::AdapterType adapterType = wgpu::AdapterType::Unknown;
27
DisplayWgpu(const egl::DisplayState & state)28 DisplayWgpu::DisplayWgpu(const egl::DisplayState &state) : DisplayImpl(state) {}
29
~DisplayWgpu()30 DisplayWgpu::~DisplayWgpu() {}
31
initialize(egl::Display * display)32 egl::Error DisplayWgpu::initialize(egl::Display *display)
33 {
34 egl::Error create_device_err = createWgpuDevice();
35 if (create_device_err.isError())
36 {
37 return create_device_err;
38 }
39 mQueue = mDevice.GetQueue();
40 return egl::NoError();
41 }
42
terminate()43 void DisplayWgpu::terminate() {}
44
makeCurrent(egl::Display * display,egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)45 egl::Error DisplayWgpu::makeCurrent(egl::Display *display,
46 egl::Surface *drawSurface,
47 egl::Surface *readSurface,
48 gl::Context *context)
49 {
50 // Ensure that the correct global DebugAnnotator is installed when the end2end tests change
51 // the ANGLE back-end (done frequently).
52 display->setGlobalDebugAnnotator();
53
54 return egl::NoError();
55 }
56
generateConfigs()57 egl::ConfigSet DisplayWgpu::generateConfigs()
58 {
59 egl::Config config;
60 config.renderTargetFormat = GL_RGBA8;
61 config.depthStencilFormat = GL_DEPTH24_STENCIL8;
62 config.bufferSize = 32;
63 config.redSize = 8;
64 config.greenSize = 8;
65 config.blueSize = 8;
66 config.alphaSize = 8;
67 config.alphaMaskSize = 0;
68 config.bindToTextureRGB = EGL_TRUE;
69 config.bindToTextureRGBA = EGL_TRUE;
70 config.colorBufferType = EGL_RGB_BUFFER;
71 config.configCaveat = EGL_NONE;
72 config.conformant = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
73 config.depthSize = 24;
74 config.level = 0;
75 config.matchNativePixmap = EGL_NONE;
76 config.maxPBufferWidth = 0;
77 config.maxPBufferHeight = 0;
78 config.maxPBufferPixels = 0;
79 config.maxSwapInterval = 1;
80 config.minSwapInterval = 1;
81 config.nativeRenderable = EGL_TRUE;
82 config.nativeVisualID = 0;
83 config.nativeVisualType = EGL_NONE;
84 config.renderableType = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
85 config.sampleBuffers = 0;
86 config.samples = 0;
87 config.stencilSize = 8;
88 config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
89 config.optimalOrientation = 0;
90 config.transparentType = EGL_NONE;
91 config.transparentRedValue = 0;
92 config.transparentGreenValue = 0;
93 config.transparentBlueValue = 0;
94
95 egl::ConfigSet configSet;
96 configSet.add(config);
97 return configSet;
98 }
99
testDeviceLost()100 bool DisplayWgpu::testDeviceLost()
101 {
102 return false;
103 }
104
restoreLostDevice(const egl::Display * display)105 egl::Error DisplayWgpu::restoreLostDevice(const egl::Display *display)
106 {
107 return egl::NoError();
108 }
109
isValidNativeWindow(EGLNativeWindowType window) const110 bool DisplayWgpu::isValidNativeWindow(EGLNativeWindowType window) const
111 {
112 return true;
113 }
114
getRendererDescription()115 std::string DisplayWgpu::getRendererDescription()
116 {
117 return "Wgpu";
118 }
119
getVendorString()120 std::string DisplayWgpu::getVendorString()
121 {
122 return "Wgpu";
123 }
124
getVersionString(bool includeFullVersion)125 std::string DisplayWgpu::getVersionString(bool includeFullVersion)
126 {
127 return std::string();
128 }
129
createDevice()130 DeviceImpl *DisplayWgpu::createDevice()
131 {
132 return new DeviceWgpu();
133 }
134
waitClient(const gl::Context * context)135 egl::Error DisplayWgpu::waitClient(const gl::Context *context)
136 {
137 return egl::NoError();
138 }
139
waitNative(const gl::Context * context,EGLint engine)140 egl::Error DisplayWgpu::waitNative(const gl::Context *context, EGLint engine)
141 {
142 return egl::NoError();
143 }
144
getMaxSupportedESVersion() const145 gl::Version DisplayWgpu::getMaxSupportedESVersion() const
146 {
147 return gl::Version(3, 2);
148 }
149
getMaxSupportedDesktopVersion() const150 Optional<gl::Version> DisplayWgpu::getMaxSupportedDesktopVersion() const
151 {
152 return Optional<gl::Version>::Invalid();
153 }
154
getMaxConformantESVersion() const155 gl::Version DisplayWgpu::getMaxConformantESVersion() const
156 {
157 return getMaxSupportedESVersion();
158 }
159
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)160 SurfaceImpl *DisplayWgpu::createWindowSurface(const egl::SurfaceState &state,
161 EGLNativeWindowType window,
162 const egl::AttributeMap &attribs)
163 {
164 return new SurfaceWgpu(state);
165 }
166
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)167 SurfaceImpl *DisplayWgpu::createPbufferSurface(const egl::SurfaceState &state,
168 const egl::AttributeMap &attribs)
169 {
170 return new SurfaceWgpu(state);
171 }
172
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer buffer,const egl::AttributeMap & attribs)173 SurfaceImpl *DisplayWgpu::createPbufferFromClientBuffer(const egl::SurfaceState &state,
174 EGLenum buftype,
175 EGLClientBuffer buffer,
176 const egl::AttributeMap &attribs)
177 {
178 return new SurfaceWgpu(state);
179 }
180
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)181 SurfaceImpl *DisplayWgpu::createPixmapSurface(const egl::SurfaceState &state,
182 NativePixmapType nativePixmap,
183 const egl::AttributeMap &attribs)
184 {
185 return new SurfaceWgpu(state);
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
getInstance() const218 wgpu::Instance DisplayWgpu::getInstance() const
219 {
220 return mInstance->Get();
221 }
222
generateExtensions(egl::DisplayExtensions * outExtensions) const223 void DisplayWgpu::generateExtensions(egl::DisplayExtensions *outExtensions) const
224 {
225 outExtensions->createContextRobustness = true;
226 outExtensions->postSubBuffer = true;
227 outExtensions->createContext = true;
228 outExtensions->image = true;
229 outExtensions->imageBase = true;
230 outExtensions->glTexture2DImage = true;
231 outExtensions->glTextureCubemapImage = true;
232 outExtensions->glTexture3DImage = true;
233 outExtensions->glRenderbufferImage = true;
234 outExtensions->getAllProcAddresses = true;
235 outExtensions->noConfigContext = true;
236 outExtensions->directComposition = true;
237 outExtensions->createContextNoError = true;
238 outExtensions->createContextWebGLCompatibility = true;
239 outExtensions->createContextBindGeneratesResource = true;
240 outExtensions->swapBuffersWithDamage = true;
241 outExtensions->pixelFormatFloat = true;
242 outExtensions->surfacelessContext = true;
243 outExtensions->displayTextureShareGroup = true;
244 outExtensions->displaySemaphoreShareGroup = true;
245 outExtensions->createContextClientArrays = true;
246 outExtensions->programCacheControlANGLE = true;
247 outExtensions->robustResourceInitializationANGLE = true;
248 }
249
generateCaps(egl::Caps * outCaps) const250 void DisplayWgpu::generateCaps(egl::Caps *outCaps) const
251 {
252 outCaps->textureNPOT = true;
253 }
254
createWgpuDevice()255 egl::Error DisplayWgpu::createWgpuDevice()
256 {
257 dawnProcSetProcs(&dawn::native::GetProcs());
258
259 WGPUInstanceDescriptor instanceDescriptor{};
260 instanceDescriptor.features.timedWaitAnyEnable = true;
261 mInstance = std::make_unique<dawn::native::Instance>(&instanceDescriptor);
262
263 // Get an adapter for the backend to use, and create the device.
264 auto adapters = mInstance->EnumerateAdapters();
265 wgpu::DawnAdapterPropertiesPowerPreference power_props{};
266 wgpu::AdapterProperties adapterProperties{};
267 adapterProperties.nextInChain = &power_props;
268
269 auto isAdapterType = [&adapterProperties](const auto &adapter) -> bool {
270 // picks the first adapter when adapterType is unknown.
271 if (adapterType == wgpu::AdapterType::Unknown)
272 {
273 return true;
274 }
275 adapter.GetProperties(&adapterProperties);
276 return adapterProperties.adapterType == adapterType;
277 };
278
279 auto preferredAdapter = std::find_if(adapters.begin(), adapters.end(), isAdapterType);
280 if (preferredAdapter == adapters.end())
281 {
282 fprintf(stderr, "Failed to find an adapter! Please try another adapter type.\n");
283 return egl::EglNotInitialized();
284 }
285
286 WGPUDeviceDescriptor deviceDesc = {};
287 mDevice = wgpu::Device::Acquire(preferredAdapter->CreateDevice(&deviceDesc));
288 mDevice.SetUncapturedErrorCallback(
289 [](WGPUErrorType type, const char *message, void *userdata) {
290 ERR() << "Error: " << type << " - message: " << message;
291 },
292 nullptr);
293 return egl::NoError();
294 }
295
CreateWgpuDisplay(const egl::DisplayState & state)296 DisplayImpl *CreateWgpuDisplay(const egl::DisplayState &state)
297 {
298 return new DisplayWgpu(state);
299 }
300
301 } // namespace rx
302