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