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