blob: d25cdf3d64a0e3dc5075f6c8b77c2c3850463b1d [file] [log] [blame]
//
// 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;
}
}