michael@0: #include "precompiled.h" michael@0: // michael@0: // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: // RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers michael@0: // retained by Renderbuffers. michael@0: michael@0: #include "libGLESv2/renderer/RenderTarget11.h" michael@0: #include "libGLESv2/renderer/Renderer11.h" michael@0: michael@0: #include "libGLESv2/renderer/renderer11_utils.h" michael@0: #include "libGLESv2/main.h" michael@0: michael@0: namespace rx michael@0: { michael@0: michael@0: static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view) michael@0: { michael@0: D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; michael@0: view->GetDesc(&rtvDesc); michael@0: michael@0: D3D11_TEXTURE2D_DESC texDesc; michael@0: texture->GetDesc(&texDesc); michael@0: michael@0: unsigned int mipSlice = 0; michael@0: unsigned int arraySlice = 0; michael@0: unsigned int mipLevels = texDesc.MipLevels; michael@0: michael@0: switch (rtvDesc.ViewDimension) michael@0: { michael@0: case D3D11_RTV_DIMENSION_TEXTURE1D: michael@0: mipSlice = rtvDesc.Texture1D.MipSlice; michael@0: arraySlice = 0; michael@0: break; michael@0: michael@0: case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: michael@0: mipSlice = rtvDesc.Texture1DArray.MipSlice; michael@0: arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; michael@0: break; michael@0: michael@0: case D3D11_RTV_DIMENSION_TEXTURE2D: michael@0: mipSlice = rtvDesc.Texture2D.MipSlice; michael@0: arraySlice = 0; michael@0: break; michael@0: michael@0: case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: michael@0: mipSlice = rtvDesc.Texture2DArray.MipSlice; michael@0: arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; michael@0: break; michael@0: michael@0: case D3D11_RTV_DIMENSION_TEXTURE2DMS: michael@0: mipSlice = 0; michael@0: arraySlice = 0; michael@0: break; michael@0: michael@0: case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: michael@0: mipSlice = 0; michael@0: arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; michael@0: break; michael@0: michael@0: case D3D11_RTV_DIMENSION_TEXTURE3D: michael@0: mipSlice = rtvDesc.Texture3D.MipSlice; michael@0: arraySlice = 0; michael@0: break; michael@0: michael@0: case D3D11_RTV_DIMENSION_UNKNOWN: michael@0: case D3D11_RTV_DIMENSION_BUFFER: michael@0: UNIMPLEMENTED(); michael@0: break; michael@0: michael@0: default: michael@0: UNREACHABLE(); michael@0: break; michael@0: } michael@0: michael@0: return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); michael@0: } michael@0: michael@0: static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view) michael@0: { michael@0: D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; michael@0: view->GetDesc(&dsvDesc); michael@0: michael@0: D3D11_TEXTURE2D_DESC texDesc; michael@0: texture->GetDesc(&texDesc); michael@0: michael@0: unsigned int mipSlice = 0; michael@0: unsigned int arraySlice = 0; michael@0: unsigned int mipLevels = texDesc.MipLevels; michael@0: michael@0: switch (dsvDesc.ViewDimension) michael@0: { michael@0: case D3D11_DSV_DIMENSION_TEXTURE1D: michael@0: mipSlice = dsvDesc.Texture1D.MipSlice; michael@0: arraySlice = 0; michael@0: break; michael@0: michael@0: case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: michael@0: mipSlice = dsvDesc.Texture1DArray.MipSlice; michael@0: arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; michael@0: break; michael@0: michael@0: case D3D11_DSV_DIMENSION_TEXTURE2D: michael@0: mipSlice = dsvDesc.Texture2D.MipSlice; michael@0: arraySlice = 0; michael@0: break; michael@0: michael@0: case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: michael@0: mipSlice = dsvDesc.Texture2DArray.MipSlice; michael@0: arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; michael@0: break; michael@0: michael@0: case D3D11_DSV_DIMENSION_TEXTURE2DMS: michael@0: mipSlice = 0; michael@0: arraySlice = 0; michael@0: break; michael@0: michael@0: case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: michael@0: mipSlice = 0; michael@0: arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; michael@0: break; michael@0: michael@0: case D3D11_RTV_DIMENSION_UNKNOWN: michael@0: UNIMPLEMENTED(); michael@0: break; michael@0: michael@0: default: michael@0: UNREACHABLE(); michael@0: break; michael@0: } michael@0: michael@0: return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); michael@0: } michael@0: michael@0: RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) michael@0: { michael@0: mRenderer = Renderer11::makeRenderer11(renderer); michael@0: mTexture = tex; michael@0: mRenderTarget = rtv; michael@0: mDepthStencil = NULL; michael@0: mShaderResource = srv; michael@0: mSubresourceIndex = 0; michael@0: michael@0: if (mRenderTarget && mTexture) michael@0: { michael@0: D3D11_RENDER_TARGET_VIEW_DESC desc; michael@0: mRenderTarget->GetDesc(&desc); michael@0: michael@0: D3D11_TEXTURE2D_DESC texDesc; michael@0: mTexture->GetDesc(&texDesc); michael@0: michael@0: mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); michael@0: mWidth = width; michael@0: mHeight = height; michael@0: mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; michael@0: michael@0: mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); michael@0: mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); michael@0: } michael@0: } michael@0: michael@0: RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) michael@0: { michael@0: mRenderer = Renderer11::makeRenderer11(renderer); michael@0: mTexture = tex; michael@0: mRenderTarget = NULL; michael@0: mDepthStencil = dsv; michael@0: mShaderResource = srv; michael@0: mSubresourceIndex = 0; michael@0: michael@0: if (mDepthStencil && mTexture) michael@0: { michael@0: D3D11_DEPTH_STENCIL_VIEW_DESC desc; michael@0: mDepthStencil->GetDesc(&desc); michael@0: michael@0: D3D11_TEXTURE2D_DESC texDesc; michael@0: mTexture->GetDesc(&texDesc); michael@0: michael@0: mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); michael@0: mWidth = width; michael@0: mHeight = height; michael@0: mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; michael@0: michael@0: mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); michael@0: mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); michael@0: } michael@0: } michael@0: michael@0: RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth) michael@0: { michael@0: mRenderer = Renderer11::makeRenderer11(renderer); michael@0: mTexture = NULL; michael@0: mRenderTarget = NULL; michael@0: mDepthStencil = NULL; michael@0: mShaderResource = NULL; michael@0: michael@0: DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format); michael@0: michael@0: int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); michael@0: if (supportedSamples < 0) michael@0: { michael@0: gl::error(GL_OUT_OF_MEMORY); michael@0: return; michael@0: } michael@0: michael@0: if (width > 0 && height > 0) michael@0: { michael@0: // Create texture resource michael@0: D3D11_TEXTURE2D_DESC desc; michael@0: desc.Width = width; michael@0: desc.Height = height; michael@0: desc.MipLevels = 1; michael@0: desc.ArraySize = 1; michael@0: desc.Format = requestedFormat; michael@0: desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; michael@0: desc.SampleDesc.Quality = 0; michael@0: desc.Usage = D3D11_USAGE_DEFAULT; michael@0: desc.CPUAccessFlags = 0; michael@0: desc.MiscFlags = 0; michael@0: desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)); michael@0: michael@0: ID3D11Device *device = mRenderer->getDevice(); michael@0: HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: gl::error(GL_OUT_OF_MEMORY); michael@0: return; michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: michael@0: if (depth) michael@0: { michael@0: D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; michael@0: dsvDesc.Format = requestedFormat; michael@0: dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; michael@0: dsvDesc.Texture2D.MipSlice = 0; michael@0: dsvDesc.Flags = 0; michael@0: result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: mTexture->Release(); michael@0: mTexture = NULL; michael@0: gl::error(GL_OUT_OF_MEMORY); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: } michael@0: else michael@0: { michael@0: D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; michael@0: rtvDesc.Format = requestedFormat; michael@0: rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; michael@0: rtvDesc.Texture2D.MipSlice = 0; michael@0: result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: mTexture->Release(); michael@0: mTexture = NULL; michael@0: gl::error(GL_OUT_OF_MEMORY); michael@0: return; michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: michael@0: D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; michael@0: srvDesc.Format = requestedFormat; michael@0: srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; michael@0: srvDesc.Texture2D.MostDetailedMip = 0; michael@0: srvDesc.Texture2D.MipLevels = 1; michael@0: result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: mTexture->Release(); michael@0: mTexture = NULL; michael@0: mRenderTarget->Release(); michael@0: mRenderTarget = NULL; michael@0: gl::error(GL_OUT_OF_MEMORY); michael@0: return; michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: } michael@0: } michael@0: michael@0: mWidth = width; michael@0: mHeight = height; michael@0: mInternalFormat = format; michael@0: mSamples = supportedSamples; michael@0: mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat); michael@0: mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); michael@0: } michael@0: michael@0: RenderTarget11::~RenderTarget11() michael@0: { michael@0: if (mTexture) michael@0: { michael@0: mTexture->Release(); michael@0: mTexture = NULL; michael@0: } michael@0: michael@0: if (mRenderTarget) michael@0: { michael@0: mRenderTarget->Release(); michael@0: mRenderTarget = NULL; michael@0: } michael@0: michael@0: if (mDepthStencil) michael@0: { michael@0: mDepthStencil->Release(); michael@0: mDepthStencil = NULL; michael@0: } michael@0: michael@0: if (mShaderResource) michael@0: { michael@0: mShaderResource->Release(); michael@0: mShaderResource = NULL; michael@0: } michael@0: } michael@0: michael@0: RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) michael@0: { michael@0: ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target)); michael@0: return static_cast(target); michael@0: } michael@0: michael@0: ID3D11Texture2D *RenderTarget11::getTexture() const michael@0: { michael@0: return mTexture; michael@0: } michael@0: michael@0: ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const michael@0: { michael@0: return mRenderTarget; michael@0: } michael@0: michael@0: ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const michael@0: { michael@0: return mDepthStencil; michael@0: } michael@0: michael@0: ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const michael@0: { michael@0: return mShaderResource; michael@0: } michael@0: michael@0: unsigned int RenderTarget11::getSubresourceIndex() const michael@0: { michael@0: return mSubresourceIndex; michael@0: } michael@0: michael@0: }