diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp new file mode 100644 index 0000000000..1970daf62d --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -0,0 +1,414 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayD3D.cpp: D3D implementation of egl::Display + +#include "libANGLE/renderer/d3d/DisplayD3D.h" + +#include <EGL/eglext.h> + +#include "libANGLE/Config.h" +#include "libANGLE/Context.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Thread.h" +#include "libANGLE/histogram_macros.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" + +#if defined(ANGLE_ENABLE_D3D9) +# include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#endif // ANGLE_ENABLE_D3D9 + +#if defined(ANGLE_ENABLE_D3D11) +# include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#endif // ANGLE_ENABLE_D3D11 + +#if !defined(ANGLE_DEFAULT_D3D11) +// Enables use of the Direct3D 11 API for a default display, when available +# define ANGLE_DEFAULT_D3D11 1 +#endif + +namespace rx +{ + +typedef RendererD3D *(*CreateRendererD3DFunction)(egl::Display *); + +template <typename RendererType> +static RendererD3D *CreateTypedRendererD3D(egl::Display *display) +{ + return new RendererType(display); +} + +egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) +{ + ASSERT(outRenderer != nullptr); + + std::vector<CreateRendererD3DFunction> rendererCreationFunctions; + + if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE) + { + const auto &attribMap = display->getAttributeMap(); + EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId(); + + EGLint requestedDisplayType = static_cast<EGLint>( + attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)); + +#if defined(ANGLE_ENABLE_D3D11) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); + } +#endif + +#if defined(ANGLE_ENABLE_D3D9) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); + } +#endif + + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) + { + // The default display is requested, try the D3D9 and D3D11 renderers, order them using + // the definition of ANGLE_DEFAULT_D3D11 +#if ANGLE_DEFAULT_D3D11 +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); +# endif +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); +# endif +#else +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); +# endif +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); +# endif +#endif + } + } + else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) + { +#if defined(ANGLE_ENABLE_D3D11) + if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); + } +#endif + } + else + { + UNIMPLEMENTED(); + } + + for (size_t i = 0; i < rendererCreationFunctions.size(); i++) + { + RendererD3D *renderer = rendererCreationFunctions[i](display); + egl::Error result = renderer->initialize(); + +#if defined(ANGLE_ENABLE_D3D11) + if (renderer->getRendererClass() == RENDERER_D3D11) + { + ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS); + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11InitializeResult", result.getID(), + NUM_D3D11_INIT_ERRORS); + } +#endif + +#if defined(ANGLE_ENABLE_D3D9) + if (renderer->getRendererClass() == RENDERER_D3D9) + { + ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS); + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D9InitializeResult", result.getID(), + NUM_D3D9_INIT_ERRORS); + } +#endif + + if (!result.isError()) + { + *outRenderer = renderer; + return result; + } + + // Failed to create the renderer, try the next + SafeDelete(renderer); + } + + return egl::EglNotInitialized() << "No available renderers."; +} + +DisplayD3D::DisplayD3D(const egl::DisplayState &state) : DisplayImpl(state), mRenderer(nullptr) {} + +SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return new WindowSurfaceD3D(state, mRenderer, mDisplay, window, attribs); +} + +SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return new PbufferSurfaceD3D(state, mRenderer, mDisplay, 0, nullptr, attribs); +} + +SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return new PbufferSurfaceD3D(state, mRenderer, mDisplay, buftype, clientBuffer, attribs); +} + +SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +ImageImpl *DisplayD3D::createImage(const egl::ImageState &state, + const gl::Context *context, + EGLenum target, + const egl::AttributeMap &attribs) +{ + return new EGLImageD3D(state, target, attribs, mRenderer); +} + +DeviceImpl *DisplayD3D::createDevice() +{ + return mRenderer->createEGLDevice(); +} + +rx::ContextImpl *DisplayD3D::createContext(const gl::State &state, + gl::ErrorSet *errorSet, + const egl::Config *configuration, + const gl::Context *shareContext, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return mRenderer->createContext(state, errorSet); +} + +StreamProducerImpl *DisplayD3D::createStreamProducerD3DTexture( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return mRenderer->createStreamProducerD3DTexture(consumerType, attribs); +} + +ExternalImageSiblingImpl *DisplayD3D::createExternalImageSibling(const gl::Context *context, + EGLenum target, + EGLClientBuffer buffer, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return mRenderer->createExternalImageSibling(context, target, buffer, attribs); +} + +egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, + egl::Surface *readSurface, + gl::Context *context) +{ + return egl::NoError(); +} + +egl::Error DisplayD3D::initialize(egl::Display *display) +{ + ASSERT(mRenderer == nullptr && display != nullptr); + mDisplay = display; + ANGLE_TRY(CreateRendererD3D(display, &mRenderer)); + return egl::NoError(); +} + +void DisplayD3D::terminate() +{ + SafeDelete(mRenderer); +} + +egl::ConfigSet DisplayD3D::generateConfigs() +{ + ASSERT(mRenderer != nullptr); + return mRenderer->generateConfigs(); +} + +bool DisplayD3D::testDeviceLost() +{ + ASSERT(mRenderer != nullptr); + return mRenderer->testDeviceLost(); +} + +egl::Error DisplayD3D::restoreLostDevice(const egl::Display *display) +{ + // Release surface resources to make the Reset() succeed + for (egl::Surface *surface : mState.surfaceSet) + { + ASSERT(!surface->getBoundTexture()); + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + surfaceD3D->releaseSwapChain(); + } + + if (!mRenderer->resetDevice()) + { + return egl::EglBadAlloc(); + } + + // Restore any surfaces that may have been lost + for (const egl::Surface *surface : mState.surfaceSet) + { + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + + ANGLE_TRY(surfaceD3D->resetSwapChain(display)); + } + + return egl::NoError(); +} + +bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const +{ + return mRenderer->isValidNativeWindow(window); +} + +egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const +{ + switch (buftype) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + return mRenderer->validateShareHandle(configuration, static_cast<HANDLE>(clientBuffer), + attribs); + + case EGL_D3D_TEXTURE_ANGLE: + return mRenderer->getD3DTextureInfo(configuration, + static_cast<IUnknown *>(clientBuffer), nullptr, + nullptr, nullptr, nullptr); + + default: + return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs); + } +} + +egl::Error DisplayD3D::validateImageClientBuffer(const gl::Context *context, + EGLenum target, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const +{ + switch (target) + { + case EGL_D3D11_TEXTURE_ANGLE: + { + return mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(clientBuffer), + nullptr, nullptr, nullptr, nullptr); + } + + default: + return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs); + } +} + +void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ + mRenderer->generateDisplayExtensions(outExtensions); +} + +std::string DisplayD3D::getVendorString() const +{ + std::string vendorString = "Google Inc."; + if (mRenderer) + { + vendorString += " " + mRenderer->getVendorString(); + } + + return vendorString; +} + +void DisplayD3D::generateCaps(egl::Caps *outCaps) const +{ + // Display must be initialized to generate caps + ASSERT(mRenderer != nullptr); + + outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNPOT; +} + +egl::Error DisplayD3D::waitClient(const gl::Context *context) +{ + for (egl::Surface *surface : mState.surfaceSet) + { + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + ANGLE_TRY(surfaceD3D->checkForOutOfDateSwapChain(this)); + } + + return egl::NoError(); +} + +egl::Error DisplayD3D::waitNative(const gl::Context *context, EGLint engine) +{ + egl::Surface *drawSurface = context->getCurrentDrawSurface(); + egl::Surface *readSurface = context->getCurrentReadSurface(); + + if (drawSurface != nullptr) + { + SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface); + ANGLE_TRY(drawSurfaceD3D->checkForOutOfDateSwapChain(this)); + } + + if (readSurface != nullptr) + { + SurfaceD3D *readSurfaceD3D = GetImplAs<SurfaceD3D>(readSurface); + ANGLE_TRY(readSurfaceD3D->checkForOutOfDateSwapChain(this)); + } + + return egl::NoError(); +} + +gl::Version DisplayD3D::getMaxSupportedESVersion() const +{ + return mRenderer->getMaxSupportedESVersion(); +} + +gl::Version DisplayD3D::getMaxConformantESVersion() const +{ + return mRenderer->getMaxConformantESVersion(); +} + +void DisplayD3D::handleResult(HRESULT hr, + const char *message, + const char *file, + const char *function, + unsigned int line) +{ + ASSERT(FAILED(hr)); + + std::stringstream errorStream; + errorStream << "Internal D3D11 error: " << gl::FmtHR(hr) << ", in " << file << ", " << function + << ":" << line << ". " << message; + + mStoredErrorString = errorStream.str(); +} + +void DisplayD3D::populateFeatureList(angle::FeatureList *features) +{ + mRenderer->getFeatures().populateFeatureList(features); +} + +} // namespace rx |