xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2014 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 
7 // DisplayD3D.cpp: D3D implementation of egl::Display
8 
9 #include "libANGLE/renderer/d3d/DisplayD3D.h"
10 
11 #include <EGL/eglext.h>
12 
13 #include "libANGLE/Config.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/Surface.h"
17 #include "libANGLE/Thread.h"
18 #include "libANGLE/histogram_macros.h"
19 #include "libANGLE/renderer/d3d/EGLImageD3D.h"
20 #include "libANGLE/renderer/d3d/RendererD3D.h"
21 #include "libANGLE/renderer/d3d/SurfaceD3D.h"
22 #include "libANGLE/renderer/d3d/SwapChainD3D.h"
23 
24 #if !defined(ANGLE_DEFAULT_D3D11)
25 // Enables use of the Direct3D 11 API for a default display, when available
26 #    define ANGLE_DEFAULT_D3D11 1
27 #endif
28 
29 namespace rx
30 {
31 
32 using CreateRendererD3DFunction = RendererD3D *(*)(egl::Display *);
33 
CreateRendererD3D(egl::Display * display,RendererD3D ** outRenderer)34 egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
35 {
36     ASSERT(outRenderer != nullptr);
37 
38     std::vector<CreateRendererD3DFunction> rendererCreationFunctions;
39 
40     if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
41     {
42         const auto &attribMap              = display->getAttributeMap();
43         EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
44 
45         EGLint requestedDisplayType = static_cast<EGLint>(
46             attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
47 
48 #if defined(ANGLE_ENABLE_D3D11)
49         const auto addD3D11 = nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
50                               nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE ||
51                               requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
52 #endif
53 
54 #if defined(ANGLE_ENABLE_D3D9)
55         const auto addD3D9 = nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
56                              requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
57 #endif
58 
59 #if ANGLE_DEFAULT_D3D11
60 #    if defined(ANGLE_ENABLE_D3D11)
61         if (addD3D11)
62         {
63             rendererCreationFunctions.push_back(CreateRenderer11);
64         }
65 #    endif
66 
67 #    if defined(ANGLE_ENABLE_D3D9)
68         if (addD3D9)
69         {
70             rendererCreationFunctions.push_back(CreateRenderer9);
71         }
72 #    endif
73 #else
74 #    if defined(ANGLE_ENABLE_D3D9)
75         if (addD3D9)
76         {
77             rendererCreationFunctions.push_back(CreateRenderer9);
78         }
79 #    endif
80 
81 #    if defined(ANGLE_ENABLE_D3D11)
82         if (addD3D11)
83         {
84             rendererCreationFunctions.push_back(CreateRenderer11);
85         }
86 #    endif
87 #endif
88 
89         if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
90             nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
91             requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
92         {
93             // The default display is requested, try the D3D9 and D3D11 renderers, order them using
94             // the definition of ANGLE_DEFAULT_D3D11
95 #if ANGLE_DEFAULT_D3D11
96 #    if defined(ANGLE_ENABLE_D3D11)
97             rendererCreationFunctions.push_back(CreateRenderer11);
98 #    endif
99 #    if defined(ANGLE_ENABLE_D3D9)
100             rendererCreationFunctions.push_back(CreateRenderer9);
101 #    endif
102 #else
103 #    if defined(ANGLE_ENABLE_D3D9)
104             rendererCreationFunctions.push_back(CreateRenderer9);
105 #    endif
106 #    if defined(ANGLE_ENABLE_D3D11)
107             rendererCreationFunctions.push_back(CreateRenderer11);
108 #    endif
109 #endif
110         }
111     }
112     else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
113     {
114 #if defined(ANGLE_ENABLE_D3D11)
115         if (display->getDevice()->getExtensions().deviceD3D11)
116         {
117             rendererCreationFunctions.push_back(CreateRenderer11);
118         }
119 #endif
120     }
121     else
122     {
123         UNIMPLEMENTED();
124     }
125 
126     for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
127     {
128         RendererD3D *renderer = rendererCreationFunctions[i](display);
129         egl::Error result     = renderer->initialize();
130 
131 #if defined(ANGLE_ENABLE_D3D11)
132         if (renderer->getRendererClass() == RENDERER_D3D11)
133         {
134             ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS);
135             ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11InitializeResult", result.getID(),
136                                         NUM_D3D11_INIT_ERRORS);
137         }
138 #endif
139 
140 #if defined(ANGLE_ENABLE_D3D9)
141         if (renderer->getRendererClass() == RENDERER_D3D9)
142         {
143             ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS);
144             ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D9InitializeResult", result.getID(),
145                                         NUM_D3D9_INIT_ERRORS);
146         }
147 #endif
148 
149         if (!result.isError())
150         {
151             *outRenderer = renderer;
152             return result;
153         }
154 
155         // Failed to create the renderer, try the next
156         SafeDelete(renderer);
157         ERR() << "Failed to create D3D renderer: " << result.getMessage();
158     }
159 
160     return egl::EglNotInitialized() << "No available renderers.";
161 }
162 
DisplayD3D(const egl::DisplayState & state)163 DisplayD3D::DisplayD3D(const egl::DisplayState &state) : DisplayImpl(state), mRenderer(nullptr) {}
164 
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)165 SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state,
166                                              EGLNativeWindowType window,
167                                              const egl::AttributeMap &attribs)
168 {
169     ASSERT(mRenderer != nullptr);
170     return new WindowSurfaceD3D(state, mRenderer, mDisplay, window, attribs);
171 }
172 
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)173 SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state,
174                                               const egl::AttributeMap &attribs)
175 {
176     ASSERT(mRenderer != nullptr);
177     return new PbufferSurfaceD3D(state, mRenderer, mDisplay, 0, nullptr, attribs);
178 }
179 
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)180 SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state,
181                                                        EGLenum buftype,
182                                                        EGLClientBuffer clientBuffer,
183                                                        const egl::AttributeMap &attribs)
184 {
185     ASSERT(mRenderer != nullptr);
186     return new PbufferSurfaceD3D(state, mRenderer, mDisplay, buftype, clientBuffer, attribs);
187 }
188 
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)189 SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state,
190                                              NativePixmapType nativePixmap,
191                                              const egl::AttributeMap &attribs)
192 {
193     UNIMPLEMENTED();
194     return nullptr;
195 }
196 
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)197 ImageImpl *DisplayD3D::createImage(const egl::ImageState &state,
198                                    const gl::Context *context,
199                                    EGLenum target,
200                                    const egl::AttributeMap &attribs)
201 {
202     return new EGLImageD3D(state, target, attribs, mRenderer);
203 }
204 
createDevice()205 DeviceImpl *DisplayD3D::createDevice()
206 {
207     return mRenderer->createEGLDevice();
208 }
209 
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)210 rx::ContextImpl *DisplayD3D::createContext(const gl::State &state,
211                                            gl::ErrorSet *errorSet,
212                                            const egl::Config *configuration,
213                                            const gl::Context *shareContext,
214                                            const egl::AttributeMap &attribs)
215 {
216     ASSERT(mRenderer != nullptr);
217     return mRenderer->createContext(state, errorSet);
218 }
219 
createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)220 StreamProducerImpl *DisplayD3D::createStreamProducerD3DTexture(
221     egl::Stream::ConsumerType consumerType,
222     const egl::AttributeMap &attribs)
223 {
224     ASSERT(mRenderer != nullptr);
225     return mRenderer->createStreamProducerD3DTexture(consumerType, attribs);
226 }
227 
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)228 ExternalImageSiblingImpl *DisplayD3D::createExternalImageSibling(const gl::Context *context,
229                                                                  EGLenum target,
230                                                                  EGLClientBuffer buffer,
231                                                                  const egl::AttributeMap &attribs)
232 {
233     ASSERT(mRenderer != nullptr);
234     return mRenderer->createExternalImageSibling(context, target, buffer, attribs);
235 }
236 
createShareGroup(const egl::ShareGroupState & state)237 ShareGroupImpl *DisplayD3D::createShareGroup(const egl::ShareGroupState &state)
238 {
239     return new ShareGroupD3D(state);
240 }
241 
makeCurrent(egl::Display * display,egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)242 egl::Error DisplayD3D::makeCurrent(egl::Display *display,
243                                    egl::Surface *drawSurface,
244                                    egl::Surface *readSurface,
245                                    gl::Context *context)
246 {
247     // Ensure the appropriate global DebugAnnotator is used
248     ASSERT(mRenderer != nullptr);
249     mRenderer->setGlobalDebugAnnotator();
250 
251     return egl::NoError();
252 }
253 
initialize(egl::Display * display)254 egl::Error DisplayD3D::initialize(egl::Display *display)
255 {
256     ASSERT(mRenderer == nullptr && display != nullptr);
257     mDisplay = display;
258     ANGLE_TRY(CreateRendererD3D(display, &mRenderer));
259     return egl::NoError();
260 }
261 
terminate()262 void DisplayD3D::terminate()
263 {
264     SafeDelete(mRenderer);
265 }
266 
generateConfigs()267 egl::ConfigSet DisplayD3D::generateConfigs()
268 {
269     ASSERT(mRenderer != nullptr);
270     return mRenderer->generateConfigs();
271 }
272 
testDeviceLost()273 bool DisplayD3D::testDeviceLost()
274 {
275     ASSERT(mRenderer != nullptr);
276     return mRenderer->testDeviceLost();
277 }
278 
restoreLostDevice(const egl::Display * display)279 egl::Error DisplayD3D::restoreLostDevice(const egl::Display *display)
280 {
281     // Release surface resources to make the Reset() succeed
282     for (auto surface : mState.surfaceMap)
283     {
284         ASSERT(!surface.second->getBoundTexture());
285         SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface.second);
286         surfaceD3D->releaseSwapChain();
287     }
288 
289     if (!mRenderer->resetDevice())
290     {
291         return egl::EglBadAlloc();
292     }
293 
294     // Restore any surfaces that may have been lost
295     for (auto surface : mState.surfaceMap)
296     {
297         SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface.second);
298 
299         ANGLE_TRY(surfaceD3D->resetSwapChain(display));
300     }
301 
302     return egl::NoError();
303 }
304 
isValidNativeWindow(EGLNativeWindowType window) const305 bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
306 {
307     return mRenderer->isValidNativeWindow(window);
308 }
309 
validateClientBuffer(const egl::Config * config,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const310 egl::Error DisplayD3D::validateClientBuffer(const egl::Config *config,
311                                             EGLenum buftype,
312                                             EGLClientBuffer clientBuffer,
313                                             const egl::AttributeMap &attribs) const
314 {
315     switch (buftype)
316     {
317         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
318             return mRenderer->validateShareHandle(config, static_cast<HANDLE>(clientBuffer),
319                                                   attribs);
320 
321         case EGL_D3D_TEXTURE_ANGLE:
322             return mRenderer->getD3DTextureInfo(config, static_cast<IUnknown *>(clientBuffer),
323                                                 attribs, nullptr, nullptr, nullptr, nullptr,
324                                                 nullptr, nullptr);
325 
326         default:
327             return DisplayImpl::validateClientBuffer(config, buftype, clientBuffer, attribs);
328     }
329 }
330 
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const331 egl::Error DisplayD3D::validateImageClientBuffer(const gl::Context *context,
332                                                  EGLenum target,
333                                                  EGLClientBuffer clientBuffer,
334                                                  const egl::AttributeMap &attribs) const
335 {
336     switch (target)
337     {
338         case EGL_D3D11_TEXTURE_ANGLE:
339         {
340             return mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(clientBuffer),
341                                                 attribs, nullptr, nullptr, nullptr, nullptr,
342                                                 nullptr, nullptr);
343         }
344 
345         default:
346             return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs);
347     }
348 }
349 
generateExtensions(egl::DisplayExtensions * outExtensions) const350 void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
351 {
352     mRenderer->generateDisplayExtensions(outExtensions);
353 }
354 
getRendererDescription()355 std::string DisplayD3D::getRendererDescription()
356 {
357     if (mRenderer)
358     {
359         return mRenderer->getRendererDescription();
360     }
361     return std::string();
362 }
363 
getVendorString()364 std::string DisplayD3D::getVendorString()
365 {
366     if (mRenderer)
367     {
368         return mRenderer->getVendorString();
369     }
370     return std::string();
371 }
372 
getVersionString(bool includeFullVersion)373 std::string DisplayD3D::getVersionString(bool includeFullVersion)
374 {
375     if (mRenderer)
376     {
377         return mRenderer->getVersionString(includeFullVersion);
378     }
379     return std::string();
380 }
381 
generateCaps(egl::Caps * outCaps) const382 void DisplayD3D::generateCaps(egl::Caps *outCaps) const
383 {
384     // Display must be initialized to generate caps
385     ASSERT(mRenderer != nullptr);
386 
387     outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNpotOES;
388 }
389 
waitClient(const gl::Context * context)390 egl::Error DisplayD3D::waitClient(const gl::Context *context)
391 {
392     for (auto surface : mState.surfaceMap)
393     {
394         SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface.second);
395         ANGLE_TRY(surfaceD3D->checkForOutOfDateSwapChain(this));
396     }
397 
398     return egl::NoError();
399 }
400 
waitNative(const gl::Context * context,EGLint engine)401 egl::Error DisplayD3D::waitNative(const gl::Context *context, EGLint engine)
402 {
403     egl::Surface *drawSurface = context->getCurrentDrawSurface();
404     egl::Surface *readSurface = context->getCurrentReadSurface();
405 
406     if (drawSurface != nullptr)
407     {
408         SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface);
409         ANGLE_TRY(drawSurfaceD3D->checkForOutOfDateSwapChain(this));
410     }
411 
412     if (readSurface != nullptr)
413     {
414         SurfaceD3D *readSurfaceD3D = GetImplAs<SurfaceD3D>(readSurface);
415         ANGLE_TRY(readSurfaceD3D->checkForOutOfDateSwapChain(this));
416     }
417 
418     return egl::NoError();
419 }
420 
getMaxSupportedESVersion() const421 gl::Version DisplayD3D::getMaxSupportedESVersion() const
422 {
423     return mRenderer->getMaxSupportedESVersion();
424 }
425 
getMaxConformantESVersion() const426 gl::Version DisplayD3D::getMaxConformantESVersion() const
427 {
428     return mRenderer->getMaxConformantESVersion();
429 }
430 
handleResult(HRESULT hr,const char * message,const char * file,const char * function,unsigned int line)431 void DisplayD3D::handleResult(HRESULT hr,
432                               const char *message,
433                               const char *file,
434                               const char *function,
435                               unsigned int line)
436 {
437     ASSERT(FAILED(hr));
438 
439     std::stringstream errorStream;
440     errorStream << "Internal D3D11 error: " << gl::FmtHR(hr) << ", in " << file << ", " << function
441                 << ":" << line << ". " << message;
442 
443     mStoredErrorString = errorStream.str();
444 }
445 
initializeFrontendFeatures(angle::FrontendFeatures * features) const446 void DisplayD3D::initializeFrontendFeatures(angle::FrontendFeatures *features) const
447 {
448     mRenderer->initializeFrontendFeatures(features);
449 }
450 
populateFeatureList(angle::FeatureList * features)451 void DisplayD3D::populateFeatureList(angle::FeatureList *features)
452 {
453     mRenderer->getFeatures().populateFeatureList(features);
454 }
455 
456 }  // namespace rx
457