| // |
| // Copyright (c) 2012 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. |
| // |
| |
| // RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers |
| // retained by Renderbuffers. |
| |
| #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" |
| |
| #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" |
| #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" |
| #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" |
| #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" |
| #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" |
| |
| namespace rx |
| { |
| |
| static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) |
| { |
| ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource); |
| if (texture1D) |
| { |
| D3D11_TEXTURE1D_DESC texDesc; |
| texture1D->GetDesc(&texDesc); |
| SafeRelease(texture1D); |
| |
| *mipLevels = texDesc.MipLevels; |
| *samples = 0; |
| |
| return true; |
| } |
| |
| ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource); |
| if (texture2D) |
| { |
| D3D11_TEXTURE2D_DESC texDesc; |
| texture2D->GetDesc(&texDesc); |
| SafeRelease(texture2D); |
| |
| *mipLevels = texDesc.MipLevels; |
| *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0; |
| |
| return true; |
| } |
| |
| ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(resource); |
| if (texture3D) |
| { |
| D3D11_TEXTURE3D_DESC texDesc; |
| texture3D->GetDesc(&texDesc); |
| SafeRelease(texture3D); |
| |
| *mipLevels = texDesc.MipLevels; |
| *samples = 0; |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) |
| { |
| D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; |
| view->GetDesc(&rtvDesc); |
| |
| unsigned int mipSlice = 0; |
| unsigned int arraySlice = 0; |
| |
| switch (rtvDesc.ViewDimension) |
| { |
| case D3D11_RTV_DIMENSION_TEXTURE1D: |
| mipSlice = rtvDesc.Texture1D.MipSlice; |
| arraySlice = 0; |
| break; |
| |
| case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: |
| mipSlice = rtvDesc.Texture1DArray.MipSlice; |
| arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; |
| break; |
| |
| case D3D11_RTV_DIMENSION_TEXTURE2D: |
| mipSlice = rtvDesc.Texture2D.MipSlice; |
| arraySlice = 0; |
| break; |
| |
| case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: |
| mipSlice = rtvDesc.Texture2DArray.MipSlice; |
| arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; |
| break; |
| |
| case D3D11_RTV_DIMENSION_TEXTURE2DMS: |
| mipSlice = 0; |
| arraySlice = 0; |
| break; |
| |
| case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: |
| mipSlice = 0; |
| arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; |
| break; |
| |
| case D3D11_RTV_DIMENSION_TEXTURE3D: |
| mipSlice = rtvDesc.Texture3D.MipSlice; |
| arraySlice = 0; |
| break; |
| |
| case D3D11_RTV_DIMENSION_UNKNOWN: |
| case D3D11_RTV_DIMENSION_BUFFER: |
| UNIMPLEMENTED(); |
| break; |
| |
| default: |
| UNREACHABLE(); |
| break; |
| } |
| |
| unsigned int mipLevels, samples; |
| getTextureProperties(resource, &mipLevels, &samples); |
| |
| return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); |
| } |
| |
| static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) |
| { |
| D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; |
| view->GetDesc(&dsvDesc); |
| |
| unsigned int mipSlice = 0; |
| unsigned int arraySlice = 0; |
| |
| switch (dsvDesc.ViewDimension) |
| { |
| case D3D11_DSV_DIMENSION_TEXTURE1D: |
| mipSlice = dsvDesc.Texture1D.MipSlice; |
| arraySlice = 0; |
| break; |
| |
| case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: |
| mipSlice = dsvDesc.Texture1DArray.MipSlice; |
| arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; |
| break; |
| |
| case D3D11_DSV_DIMENSION_TEXTURE2D: |
| mipSlice = dsvDesc.Texture2D.MipSlice; |
| arraySlice = 0; |
| break; |
| |
| case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: |
| mipSlice = dsvDesc.Texture2DArray.MipSlice; |
| arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; |
| break; |
| |
| case D3D11_DSV_DIMENSION_TEXTURE2DMS: |
| mipSlice = 0; |
| arraySlice = 0; |
| break; |
| |
| case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: |
| mipSlice = 0; |
| arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; |
| break; |
| |
| case D3D11_DSV_DIMENSION_UNKNOWN: |
| UNIMPLEMENTED(); |
| break; |
| |
| default: |
| UNREACHABLE(); |
| break; |
| } |
| |
| unsigned int mipLevels, samples; |
| getTextureProperties(resource, &mipLevels, &samples); |
| |
| return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); |
| } |
| |
| RenderTarget11::RenderTarget11(d3d11::ANGLEFormat angleFormat) : mANGLEFormat(angleFormat) |
| { |
| } |
| |
| RenderTarget11::~RenderTarget11() |
| { |
| signalDirty(); |
| } |
| |
| void RenderTarget11::addDirtyCallback(const NotificationCallback *callback) |
| { |
| mDirtyCallbacks.add(callback); |
| } |
| |
| void RenderTarget11::removeDirtyCallback(const NotificationCallback *callback) |
| { |
| mDirtyCallbacks.remove(callback); |
| } |
| |
| void RenderTarget11::signalDirty() |
| { |
| mDirtyCallbacks.signal(); |
| |
| // Clear the signal list. We can't do this in the callback because it mutates the iterator. |
| mDirtyCallbacks.clear(); |
| } |
| |
| TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, |
| ID3D11Resource *resource, |
| ID3D11ShaderResourceView *srv, |
| ID3D11ShaderResourceView *blitSRV, |
| GLenum internalFormat, |
| d3d11::ANGLEFormat angleFormat, |
| GLsizei width, |
| GLsizei height, |
| GLsizei depth, |
| GLsizei samples) |
| : RenderTarget11(angleFormat), |
| mWidth(width), |
| mHeight(height), |
| mDepth(depth), |
| mInternalFormat(internalFormat), |
| mSamples(samples), |
| mSubresourceIndex(0), |
| mTexture(resource), |
| mRenderTarget(rtv), |
| mDepthStencil(NULL), |
| mShaderResource(srv), |
| mBlitShaderResource(blitSRV) |
| { |
| if (mTexture) |
| { |
| mTexture->AddRef(); |
| } |
| |
| if (mRenderTarget) |
| { |
| mRenderTarget->AddRef(); |
| } |
| |
| if (mShaderResource) |
| { |
| mShaderResource->AddRef(); |
| } |
| |
| if (mBlitShaderResource) |
| { |
| mBlitShaderResource->AddRef(); |
| } |
| |
| if (mRenderTarget && mTexture) |
| { |
| mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); |
| } |
| ASSERT(mANGLEFormat != d3d11::ANGLE_FORMAT_NONE || mWidth == 0 || mHeight == 0); |
| } |
| |
| TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, |
| ID3D11Resource *resource, |
| ID3D11ShaderResourceView *srv, |
| GLenum internalFormat, |
| d3d11::ANGLEFormat angleFormat, |
| GLsizei width, |
| GLsizei height, |
| GLsizei depth, |
| GLsizei samples) |
| : RenderTarget11(angleFormat), |
| mWidth(width), |
| mHeight(height), |
| mDepth(depth), |
| mInternalFormat(internalFormat), |
| mSamples(samples), |
| mSubresourceIndex(0), |
| mTexture(resource), |
| mRenderTarget(NULL), |
| mDepthStencil(dsv), |
| mShaderResource(srv), |
| mBlitShaderResource(nullptr) |
| { |
| if (mTexture) |
| { |
| mTexture->AddRef(); |
| } |
| |
| if (mDepthStencil) |
| { |
| mDepthStencil->AddRef(); |
| } |
| |
| if (mShaderResource) |
| { |
| mShaderResource->AddRef(); |
| } |
| |
| if (mDepthStencil && mTexture) |
| { |
| mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); |
| } |
| ASSERT(mANGLEFormat != d3d11::ANGLE_FORMAT_NONE || mWidth == 0 || mHeight == 0); |
| } |
| |
| TextureRenderTarget11::~TextureRenderTarget11() |
| { |
| SafeRelease(mTexture); |
| SafeRelease(mRenderTarget); |
| SafeRelease(mDepthStencil); |
| SafeRelease(mShaderResource); |
| SafeRelease(mBlitShaderResource); |
| } |
| |
| ID3D11Resource *TextureRenderTarget11::getTexture() const |
| { |
| return mTexture; |
| } |
| |
| ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const |
| { |
| return mRenderTarget; |
| } |
| |
| ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const |
| { |
| return mDepthStencil; |
| } |
| |
| ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const |
| { |
| return mShaderResource; |
| } |
| |
| ID3D11ShaderResourceView *TextureRenderTarget11::getBlitShaderResourceView() const |
| { |
| return mBlitShaderResource; |
| } |
| |
| GLsizei TextureRenderTarget11::getWidth() const |
| { |
| return mWidth; |
| } |
| |
| GLsizei TextureRenderTarget11::getHeight() const |
| { |
| return mHeight; |
| } |
| |
| GLsizei TextureRenderTarget11::getDepth() const |
| { |
| return mDepth; |
| } |
| |
| GLenum TextureRenderTarget11::getInternalFormat() const |
| { |
| return mInternalFormat; |
| } |
| |
| GLsizei TextureRenderTarget11::getSamples() const |
| { |
| return mSamples; |
| } |
| |
| unsigned int TextureRenderTarget11::getSubresourceIndex() const |
| { |
| return mSubresourceIndex; |
| } |
| |
| SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, |
| Renderer11 *renderer, |
| bool depth) |
| : RenderTarget11(d3d11::ANGLE_FORMAT_NONE), // format will be determined in constructor body |
| mSwapChain(swapChain), |
| mRenderer(renderer), |
| mDepth(depth) |
| { |
| ASSERT(mSwapChain); |
| |
| mANGLEFormat = d3d11::GetTextureFormatInfo(getInternalFormatInternal(), |
| mRenderer->getRenderer11DeviceCaps()) |
| .formatSet->format; |
| } |
| |
| SurfaceRenderTarget11::~SurfaceRenderTarget11() |
| { |
| } |
| |
| GLsizei SurfaceRenderTarget11::getWidth() const |
| { |
| return mSwapChain->getWidth(); |
| } |
| |
| GLsizei SurfaceRenderTarget11::getHeight() const |
| { |
| return mSwapChain->getHeight(); |
| } |
| |
| GLsizei SurfaceRenderTarget11::getDepth() const |
| { |
| return 1; |
| } |
| |
| GLenum SurfaceRenderTarget11::getInternalFormat() const |
| { |
| return getInternalFormatInternal(); |
| } |
| |
| GLenum SurfaceRenderTarget11::getInternalFormatInternal() const |
| { |
| return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetRenderTargetInternalFormat()); |
| } |
| |
| GLsizei SurfaceRenderTarget11::getSamples() const |
| { |
| // Our EGL surfaces do not support multisampling. |
| return 0; |
| } |
| |
| ID3D11Resource *SurfaceRenderTarget11::getTexture() const |
| { |
| return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture()); |
| } |
| |
| ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const |
| { |
| return (mDepth ? NULL : mSwapChain->getRenderTarget()); |
| } |
| |
| ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const |
| { |
| return (mDepth ? mSwapChain->getDepthStencil() : NULL); |
| } |
| |
| ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const |
| { |
| return (mDepth ? mSwapChain->getDepthStencilShaderResource() |
| : mSwapChain->getRenderTargetShaderResource()); |
| } |
| |
| ID3D11ShaderResourceView *SurfaceRenderTarget11::getBlitShaderResourceView() const |
| { |
| // The SurfaceRenderTargetView format should always be such that the normal SRV works for blits. |
| return getShaderResourceView(); |
| } |
| |
| unsigned int SurfaceRenderTarget11::getSubresourceIndex() const |
| { |
| return 0; |
| } |
| |
| } |