diff --git a/OgreMain/include/OgreTexture.h b/OgreMain/include/OgreTexture.h index a2b90783fee..b95a0bebd33 100644 --- a/OgreMain/include/OgreTexture.h +++ b/OgreMain/include/OgreTexture.h @@ -146,6 +146,12 @@ namespace Ogre { */ TextureType getTextureType(void) const { return mTextureType; } + /** D3D11 only: set a shared surface to use for this texture before loading + * + * Useful for WPF interop + */ + virtual void _setD3D11Surface(void* surface) {} + /** Gets the number of mipmaps to be used for this texture. */ uint32 getNumMipmaps(void) const {return mNumMipmaps;} diff --git a/RenderSystems/Direct3D11/include/OgreD3D11Texture.h b/RenderSystems/Direct3D11/include/OgreD3D11Texture.h index 4a3bd9fe49d..c9cc52b4f63 100644 --- a/RenderSystems/Direct3D11/include/OgreD3D11Texture.h +++ b/RenderSystems/Direct3D11/include/OgreD3D11Texture.h @@ -94,6 +94,8 @@ namespace Ogre { void _create1DTex(); /// internal method, create a blank normal 2D texture void _create2DTex(); + /// internal method to create a normal 2D texture with an already existing surface + void _createShared2DTex(); /// internal method, create a blank cube texture void _create3DTex(); @@ -108,6 +110,8 @@ namespace Ogre { /// mipmap level. This method must be called after the D3D texture object was created void _createSurfaceList(void); + void _setD3D11Surface(void* surface) override; + void notifyDeviceLost(D3D11Device* device); void notifyDeviceRestored(D3D11Device* device); @@ -128,6 +132,8 @@ namespace Ogre { D3D11_SHADER_RESOURCE_VIEW_DESC mSRVDesc; bool mAutoMipMapGeneration; + + void* mSurface = NULL; }; /// RenderTexture implementation for D3D11 diff --git a/RenderSystems/Direct3D11/src/OgreD3D11Texture.cpp b/RenderSystems/Direct3D11/src/OgreD3D11Texture.cpp index f4635e9fdde..2100bf38ddc 100644 --- a/RenderSystems/Direct3D11/src/OgreD3D11Texture.cpp +++ b/RenderSystems/Direct3D11/src/OgreD3D11Texture.cpp @@ -233,6 +233,11 @@ namespace Ogre //--------------------------------------------------------------------- void D3D11Texture::_create2DTex() { + if (mSurface) + { + _createShared2DTex(); + return; + } // we must have those defined here assert(mSrcWidth > 0 || mSrcHeight > 0); @@ -304,6 +309,89 @@ namespace Ogre _create2DResourceView(); } //---------------------------------------------------------------------------- + void D3D11Texture::_createShared2DTex() + { + HRESULT hr = S_OK; + + IUnknown* pUnk = (IUnknown*)mSurface; + + IDXGIResource* pDXGIResource; + hr = pUnk->QueryInterface(__uuidof(IDXGIResource), (void**)&pDXGIResource); + if (FAILED(hr)) + { + this->unloadImpl(); + OGRE_EXCEPT_EX(Exception::ERR_RENDERINGAPI_ERROR, hr, + "Error creating texture\nError Description: Failed to query IDXGIResource interface from " + "the provided object.", + "D3D11Texture::_create2DTex"); + } + + HANDLE sharedHandle; + hr = pDXGIResource->GetSharedHandle(&sharedHandle); + if (FAILED(hr)) + { + this->unloadImpl(); + OGRE_EXCEPT_EX(Exception::ERR_RENDERINGAPI_ERROR, hr, + "Error creating texture\nError Description: Failed to retrieve the shared handle from " + "IDXGIResource. Ensure the resource was " + "created with the D3D11_RESOURCE_MISC_SHARED flag.", + "D3D11Texture::_create2DTex"); + } + + pDXGIResource->Release(); + + IUnknown* tempResource11; + hr = mDevice->OpenSharedResource(sharedHandle, __uuidof(ID3D11Resource), (void**)(&tempResource11)); + if (FAILED(hr)) + { + this->unloadImpl(); + OGRE_EXCEPT_EX(Exception::ERR_RENDERINGAPI_ERROR, hr, + "Error creating texture\nError Description: Failed to open shared resource using the shared " + "handle. Ensure the handle is " + "valid and the device supports shared resources.", + "D3D11Texture::_create2DTex"); + } + + ID3D11Texture2D* pOutputResource; + hr = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&pOutputResource)); + if (FAILED(hr)) + { + this->unloadImpl(); + OGRE_EXCEPT_EX(Exception::ERR_RENDERINGAPI_ERROR, hr, + "Error creating texture\nError Description: Failed to query ID3D11Texture2D interface from " + "the shared resource. Ensure the " + "resource is of the correct type.", + "D3D11Texture::_create2DTex"); + } + tempResource11->Release(); + + mp2DTex = pOutputResource; + + D3D11_TEXTURE2D_DESC desc; + mp2DTex->GetDesc(&desc); + + D3D11_RENDER_TARGET_VIEW_DESC rtDesc; + rtDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtDesc.Texture2D.MipSlice = 0; + + ComPtr renderTargetView; + hr = mDevice->CreateRenderTargetView(mp2DTex.Get(), nullptr, renderTargetView.GetAddressOf()); + if (FAILED(hr)) + { + this->unloadImpl(); + OGRE_EXCEPT_EX(Exception::ERR_RENDERINGAPI_ERROR, hr, + "Error creating texture\nError Description: Failed to create ID3D11RenderTargetView. Verify " + "that the texture is valid, " + "properly initialized, and compatible with RenderTargetView creation.", + "D3D11Texture::_create2DTex"); + } + + _queryInterface(mp2DTex, &mpTex); + + _create2DResourceView(); + } + //---------------------------------------------------------------------------- void D3D11Texture::_create2DResourceView() { // set final tex. attributes from tex. description @@ -506,6 +594,8 @@ namespace Ogre } } //--------------------------------------------------------------------- + void D3D11Texture ::_setD3D11Surface(void* surface) { mSurface = surface; } + //--------------------------------------------------------------------- // D3D11RenderTexture //--------------------------------------------------------------------- void D3D11RenderTexture::rebind( D3D11HardwarePixelBuffer *buffer )