Commit bafefdf3 by Geoff Lang

Add error handling to RenderTarget creation.

* RenderTarget9/11 don't create any resources themselves anymore. * Pass the real internal format to RenderTarget creation so that it is not lost by converting to D3D formats and back. BUG=angle:520 Change-Id: If420970d42f0bf6ce392d64f9cb7efa4df0b8f8e Reviewed-on: https://chromium-review.googlesource.com/222838Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 468d7a1e
......@@ -38,15 +38,21 @@ Renderbuffer::~Renderbuffer()
SafeDelete(mRenderbuffer);
}
void Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
{
Error error = mRenderbuffer->setStorage(width, height, internalformat, samples);
if (error.isError())
{
return error;
}
mWidth = width;
mHeight = height;
mInternalFormat = internalformat;
mSamples = samples;
mRenderbuffer->setStorage(width, height, internalformat, samples);
mActualFormat = mRenderbuffer->getActualFormat();
return Error(GL_NO_ERROR);
}
rx::RenderbufferImpl *Renderbuffer::getImplementation()
......
......@@ -13,6 +13,8 @@
#include "angle_gl.h"
#include "libGLESv2/Error.h"
#include "common/angleutils.h"
#include "common/RefCountObject.h"
......@@ -36,7 +38,7 @@ class Renderbuffer : public RefCountObject
Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
virtual ~Renderbuffer();
void setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
rx::RenderbufferImpl *getImplementation();
......
......@@ -3881,7 +3881,12 @@ void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei sa
}
gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
renderbuffer->setStorage(width, height, internalformat, samples);
gl::Error error = renderbuffer->setStorage(width, height, internalformat, samples);
if (error.isError())
{
context->recordError(error);
return;
}
}
}
......
......@@ -11,6 +11,8 @@
#include "angle_gl.h"
#include "libGLESv2/Error.h"
#include "common/angleutils.h"
namespace rx
......@@ -22,7 +24,7 @@ class RenderbufferImpl
RenderbufferImpl();
virtual ~RenderbufferImpl() = 0;
virtual void setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) = 0;
virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) = 0;
virtual GLsizei getWidth() const = 0;
virtual GLsizei getHeight() const = 0;
......
......@@ -189,8 +189,8 @@ class Renderer
GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0;
// RenderTarget creation
virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0;
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0;
virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) = 0;
virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) = 0;
// Shader creation
virtual ShaderImpl *createShader(GLenum type) = 0;
......
......@@ -39,6 +39,9 @@ class SwapChain
virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
virtual void recreate() = 0;
GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; }
GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; }
virtual HANDLE getShareHandle() {return mShareHandle;};
protected:
......
......@@ -30,7 +30,7 @@ RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbu
return static_cast<RenderbufferD3D*>(renderbuffer);
}
void RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
{
// If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
......@@ -42,16 +42,32 @@ void RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalf
creationFormat = GL_DEPTH24_STENCIL8_OES;
}
RenderTarget *newRT = mRenderer->createRenderTarget(width, height, creationFormat, samples);
RenderTarget *newRT = NULL;
gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT);
if (error.isError())
{
return error;
}
SafeDelete(mRenderTarget);
mRenderTarget = newRT;
return gl::Error(GL_NO_ERROR);
}
void RenderbufferD3D::setStorage(SwapChain *swapChain, bool depth)
gl::Error RenderbufferD3D::setStorage(SwapChain *swapChain, bool depth)
{
RenderTarget *newRT = mRenderer->createRenderTarget(swapChain, depth);
RenderTarget *newRT = NULL;
gl::Error error = mRenderer->createRenderTarget(swapChain, depth, &newRT);
if (error.isError())
{
return error;
}
SafeDelete(mRenderTarget);
mRenderTarget = newRT;
return gl::Error(GL_NO_ERROR);
}
GLsizei RenderbufferD3D::getWidth() const
......
......@@ -28,8 +28,8 @@ class RenderbufferD3D : public RenderbufferImpl
static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer);
virtual void setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
void setStorage(SwapChain *swapChain, bool depth);
virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) override;
gl::Error setStorage(SwapChain *swapChain, bool depth);
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
......
......@@ -176,234 +176,90 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth
return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
}
RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource,
ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth)
RenderTarget11::RenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples)
: mSubresourceIndex(0),
mTexture(resource),
mRenderTarget(rtv),
mDepthStencil(NULL),
mShaderResource(srv)
{
mRenderer = Renderer11::makeRenderer11(renderer);
mTexture = resource;
if (mTexture)
{
mTexture->AddRef();
}
mRenderTarget = rtv;
if (mRenderTarget)
{
mRenderTarget->AddRef();
}
mDepthStencil = NULL;
mShaderResource = srv;
if (mShaderResource)
{
mShaderResource->AddRef();
}
mSubresourceIndex = 0;
mWidth = width;
mHeight = height;
mDepth = depth;
mSamples = samples;
mInternalFormat = internalFormat;
mActualFormat = internalFormat;
if (mRenderTarget && mTexture)
{
mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
D3D11_RENDER_TARGET_VIEW_DESC desc;
mRenderTarget->GetDesc(&desc);
unsigned int mipLevels, samples;
getTextureProperties(mTexture, &mipLevels, &samples);
mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
mWidth = width;
mHeight = height;
mDepth = depth;
mSamples = samples;
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
mInternalFormat = dxgiFormatInfo.internalFormat;
mActualFormat = dxgiFormatInfo.internalFormat;
}
}
RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource,
ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth)
RenderTarget11::RenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples)
: mSubresourceIndex(0),
mTexture(resource),
mRenderTarget(NULL),
mDepthStencil(dsv),
mShaderResource(srv)
{
mRenderer = Renderer11::makeRenderer11(renderer);
mTexture = resource;
if (mTexture)
{
mTexture->AddRef();
}
mRenderTarget = NULL;
mDepthStencil = dsv;
if (mDepthStencil)
{
mDepthStencil->AddRef();
}
mShaderResource = srv;
if (mShaderResource)
{
mShaderResource->AddRef();
}
mSubresourceIndex = 0;
mWidth = width;
mHeight = height;
mDepth = depth;
mSamples = samples;
mInternalFormat = internalFormat;
mActualFormat = internalFormat;
if (mDepthStencil && mTexture)
{
mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
mDepthStencil->GetDesc(&desc);
unsigned int mipLevels, samples;
getTextureProperties(mTexture, &mipLevels, &samples);
mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
mWidth = width;
mHeight = height;
mDepth = depth;
mSamples = samples;
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
mInternalFormat = dxgiFormatInfo.internalFormat;
mActualFormat = dxgiFormatInfo.internalFormat;
}
}
RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples)
{
mRenderer = Renderer11::makeRenderer11(renderer);
mTexture = NULL;
mRenderTarget = NULL;
mDepthStencil = NULL;
mShaderResource = NULL;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat);
const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat);
GLuint supportedSamples = textureCaps.getNearestSamples(samples);
if (width > 0 && height > 0)
{
// Create texture resource
D3D11_TEXTURE2D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = formatInfo.texFormat;
desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
// If a rendertarget or depthstencil format exists for this texture format,
// we'll flag it to allow binding that way. Shader resource views are a little
// more complicated.
bool bindRTV = false, bindDSV = false, bindSRV = false;
bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
{
// Multisample targets flagged for binding as depth stencil cannot also be
// flagged for binding as SRV, so make certain not to add the SRV flag for
// these targets.
bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1);
}
desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
(bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
(bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
ID3D11Device *device = mRenderer->getDevice();
ID3D11Texture2D *texture = NULL;
HRESULT result = device->CreateTexture2D(&desc, NULL, &texture);
mTexture = texture;
if (result == E_OUTOFMEMORY)
{
gl::error(GL_OUT_OF_MEMORY);
return;
}
ASSERT(SUCCEEDED(result));
if (bindSRV)
{
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = formatInfo.srvFormat;
srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource);
if (result == E_OUTOFMEMORY)
{
SafeRelease(mTexture);
gl::error(GL_OUT_OF_MEMORY);
return;
}
ASSERT(SUCCEEDED(result));
}
if (bindDSV)
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
dsvDesc.Format = formatInfo.dsvFormat;
dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
dsvDesc.Texture2D.MipSlice = 0;
dsvDesc.Flags = 0;
result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil);
if (result == E_OUTOFMEMORY)
{
SafeRelease(mTexture);
SafeRelease(mShaderResource);
gl::error(GL_OUT_OF_MEMORY);
return;
}
ASSERT(SUCCEEDED(result));
}
if (bindRTV)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = formatInfo.rtvFormat;
rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
rtvDesc.Texture2D.MipSlice = 0;
result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget);
if (result == E_OUTOFMEMORY)
{
SafeRelease(mTexture);
SafeRelease(mShaderResource);
SafeRelease(mDepthStencil);
gl::error(GL_OUT_OF_MEMORY);
return;
}
ASSERT(SUCCEEDED(result));
if (formatInfo.dataInitializerFunction != NULL)
{
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
context->ClearRenderTargetView(mRenderTarget, clearValues);
}
}
}
mWidth = width;
mHeight = height;
mDepth = 1;
mInternalFormat = internalFormat;
mSamples = supportedSamples;
mActualFormat = dxgiFormatInfo.internalFormat;
mSubresourceIndex = D3D11CalcSubresource(0, 0, 1);
}
RenderTarget11::~RenderTarget11()
{
SafeRelease(mTexture);
......
......@@ -14,16 +14,15 @@
namespace rx
{
class Renderer;
class Renderer11;
class RenderTarget11 : public RenderTarget
{
public:
// RenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them
RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth);
RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth);
RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples);
RenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples);
RenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples);
virtual ~RenderTarget11();
static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget);
......@@ -45,8 +44,6 @@ class RenderTarget11 : public RenderTarget
ID3D11RenderTargetView *mRenderTarget;
ID3D11DepthStencilView *mDepthStencil;
ID3D11ShaderResourceView *mShaderResource;
Renderer11 *mRenderer;
};
}
......
......@@ -2188,34 +2188,164 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView
}
}
RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
gl::Error Renderer11::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT)
{
SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
RenderTarget11 *renderTarget = NULL;
if (depth)
{
// Note: depth stencil may be NULL for 0 sized surfaces
renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
swapChain11->getDepthStencilTexture(),
swapChain11->getDepthStencilShaderResource(),
swapChain11->getWidth(), swapChain11->getHeight(), 1);
*outRT = new RenderTarget11(swapChain11->getDepthStencil(),
swapChain11->getDepthStencilTexture(),
swapChain11->getDepthStencilShaderResource(),
swapChain11->GetDepthBufferInternalFormat(),
swapChain11->getWidth(), swapChain11->getHeight(), 1, 1);
}
else
{
// Note: render target may be NULL for 0 sized surfaces
renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
swapChain11->getOffscreenTexture(),
swapChain11->getRenderTargetShaderResource(),
swapChain11->getWidth(), swapChain11->getHeight(), 1);
*outRT = new RenderTarget11(swapChain11->getRenderTarget(),
swapChain11->getOffscreenTexture(),
swapChain11->getRenderTargetShaderResource(),
swapChain11->GetBackBufferInternalFormat(),
swapChain11->getWidth(), swapChain11->getHeight(), 1, 1);
}
return renderTarget;
return gl::Error(GL_NO_ERROR);
}
RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples)
gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT)
{
RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples);
return renderTarget;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format);
const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format);
GLuint supportedSamples = textureCaps.getNearestSamples(samples);
if (width > 0 && height > 0)
{
// Create texture resource
D3D11_TEXTURE2D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = formatInfo.texFormat;
desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
// If a rendertarget or depthstencil format exists for this texture format,
// we'll flag it to allow binding that way. Shader resource views are a little
// more complicated.
bool bindRTV = false, bindDSV = false, bindSRV = false;
bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
{
// Multisample targets flagged for binding as depth stencil cannot also be
// flagged for binding as SRV, so make certain not to add the SRV flag for
// these targets.
bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1);
}
desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
(bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
(bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
// The format must be either an RTV or a DSV
ASSERT(bindRTV != bindDSV);
ID3D11Texture2D *texture = NULL;
HRESULT result = mDevice->CreateTexture2D(&desc, NULL, &texture);
if (FAILED(result))
{
ASSERT(result == E_OUTOFMEMORY);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target texture, result: 0x%X.", result);
}
ID3D11ShaderResourceView *srv = NULL;
if (bindSRV)
{
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = formatInfo.srvFormat;
srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv);
if (FAILED(result))
{
ASSERT(result == E_OUTOFMEMORY);
SafeRelease(texture);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target shader resource view, result: 0x%X.", result);
}
}
if (bindDSV)
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
dsvDesc.Format = formatInfo.dsvFormat;
dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
dsvDesc.Texture2D.MipSlice = 0;
dsvDesc.Flags = 0;
ID3D11DepthStencilView *dsv = NULL;
result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv);
if (FAILED(result))
{
ASSERT(result == E_OUTOFMEMORY);
SafeRelease(texture);
SafeRelease(srv);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target depth stencil view, result: 0x%X.", result);
}
*outRT = new RenderTarget11(dsv, texture, srv, format, width, height, 1, supportedSamples);
SafeRelease(dsv);
}
else if (bindRTV)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = formatInfo.rtvFormat;
rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
rtvDesc.Texture2D.MipSlice = 0;
ID3D11RenderTargetView *rtv = NULL;
result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv);
if (FAILED(result))
{
ASSERT(result == E_OUTOFMEMORY);
SafeRelease(texture);
SafeRelease(srv);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target render target view, result: 0x%X.", result);
}
if (formatInfo.dataInitializerFunction != NULL)
{
const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
mDeviceContext->ClearRenderTargetView(rtv, clearValues);
}
*outRT = new RenderTarget11(rtv, texture, srv, format, width, height, 1, supportedSamples);
SafeRelease(rtv);
}
else
{
UNREACHABLE();
}
SafeRelease(texture);
SafeRelease(srv);
}
else
{
*outRT = new RenderTarget11(reinterpret_cast<ID3D11RenderTargetView*>(NULL), NULL, NULL, format, width, height, 1, supportedSamples);
}
return gl::Error(GL_NO_ERROR);
}
ShaderImpl *Renderer11::createShader(GLenum type)
......
......@@ -134,8 +134,8 @@ class Renderer11 : public RendererD3D
GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
// RenderTarget creation
virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples);
virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT);
virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT);
// Shader creation
virtual ShaderImpl *createShader(GLenum type);
......
......@@ -65,6 +65,7 @@ TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
: mBindFlags(bindFlags),
mTopLevel(0),
mMipLevels(0),
mInternalFormat(GL_NONE),
mTextureFormat(DXGI_FORMAT_UNKNOWN),
mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
......@@ -561,6 +562,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch
mTextureHeight = texDesc.Height;
mTextureDepth = 1;
mInternalFormat = swapchain->GetBackBufferInternalFormat();
ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource();
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srv->GetDesc(&srvDesc);
......@@ -594,6 +597,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform
mSwizzleRenderTargets[i] = NULL;
}
mInternalFormat = internalformat;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat;
......@@ -809,7 +814,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
}
mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, texture, srv, getLevelWidth(level), getLevelHeight(level), 1);
mRenderTarget[level] = new RenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 1);
// RenderTarget will take ownership of these resources
SafeRelease(rtv);
......@@ -833,7 +838,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
return gl::Error(GL_OUT_OF_MEMORY,"Failed to create internal depth stencil view for texture storage, result: 0x%X.", result);
}
mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, texture, srv, getLevelWidth(level), getLevelHeight(level), 1);
mRenderTarget[level] = new RenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 1);
// RenderTarget will take ownership of these resources
SafeRelease(dsv);
......@@ -956,6 +961,8 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal
}
}
mInternalFormat = internalformat;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat;
......@@ -1210,7 +1217,7 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
}
mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, texture, srv, getLevelWidth(level), getLevelHeight(level), 1);
mRenderTarget[faceIndex][level] = new RenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 1);
// RenderTarget will take ownership of these resources
SafeRelease(rtv);
......@@ -1236,7 +1243,7 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal depth stencil view for texture storage, result: 0x%X.", result);
}
mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, texture, srv, getLevelWidth(level), getLevelHeight(level), 1);
mRenderTarget[faceIndex][level] = new RenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 1);
// RenderTarget will take ownership of these resources
SafeRelease(dsv);
......@@ -1374,6 +1381,8 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform
mSwizzleRenderTargets[i] = NULL;
}
mInternalFormat = internalformat;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat;
......@@ -1617,7 +1626,7 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
}
mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, texture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel));
mLevelRenderTargets[mipLevel] = new RenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 1);
// RenderTarget will take ownership of these resources
SafeRelease(rtv);
......@@ -1664,7 +1673,7 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend
}
ASSERT(SUCCEEDED(result));
mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, texture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
mLevelLayerRenderTargets[key] = new RenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 1);
// RenderTarget will take ownership of these resources
SafeRelease(rtv);
......@@ -1756,6 +1765,8 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in
mSwizzleRenderTargets[level] = NULL;
}
mInternalFormat = internalformat;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat;
......@@ -2013,7 +2024,7 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index,
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
}
mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, texture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
mRenderTargets[key] = new RenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 1);
// RenderTarget will take ownership of these resources
SafeRelease(rtv);
......
......@@ -91,6 +91,7 @@ class TextureStorage11 : public TextureStorage
int mTopLevel;
unsigned int mMipLevels;
GLenum mInternalFormat;
DXGI_FORMAT mTextureFormat;
DXGI_FORMAT mShaderResourceFormat;
DXGI_FORMAT mRenderTargetFormat;
......
......@@ -17,91 +17,27 @@ namespace rx
{
// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given.
RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface)
RenderTarget9::RenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
GLsizei samples)
: mRenderTarget(surface)
{
mRenderer = Renderer9::makeRenderer9(renderer);
mRenderTarget = surface;
mWidth = width;
mHeight = height;
mDepth = depth;
mSamples = samples;
mInternalFormat = internalFormat;
mActualFormat = internalFormat;
if (mRenderTarget)
{
D3DSURFACE_DESC description;
mRenderTarget->GetDesc(&description);
mWidth = description.Width;
mHeight = description.Height;
mDepth = 1;
const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format);
mInternalFormat = d3dFormatInfo.internalFormat;
mActualFormat = d3dFormatInfo.internalFormat;
mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType);
}
}
RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples)
{
mRenderer = Renderer9::makeRenderer9(renderer);
mRenderTarget = NULL;
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.renderFormat);
const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat);
GLuint supportedSamples = textureCaps.getNearestSamples(samples);
HRESULT result = D3DERR_INVALIDCALL;
if (width > 0 && height > 0)
{
IDirect3DDevice9 *device = mRenderer->getDevice();
bool requiresInitialization = false;
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
{
result = device->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat,
gl_d3d9::GetMultisampleType(supportedSamples),
0, FALSE, &mRenderTarget, NULL);
}
else
{
requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL);
result = device->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
gl_d3d9::GetMultisampleType(supportedSamples),
0, FALSE, &mRenderTarget, NULL);
}
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
gl::error(GL_OUT_OF_MEMORY);
return;
}
ASSERT(SUCCEEDED(result));
if (requiresInitialization)
{
// This format requires that the data be initialized before the render target can be used
// Unfortunately this requires a Get call on the d3d device but it is far better than having
// to mark the render target as lockable and copy data to the gpu.
IDirect3DSurface9 *prevRenderTarget = NULL;
device->GetRenderTarget(0, &prevRenderTarget);
device->SetRenderTarget(0, mRenderTarget);
device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
device->SetRenderTarget(0, prevRenderTarget);
}
}
mWidth = width;
mHeight = height;
mDepth = 1;
mInternalFormat = internalFormat;
mSamples = supportedSamples;
mActualFormat = d3dFormatInfo.internalFormat;
}
RenderTarget9::~RenderTarget9()
{
SafeRelease(mRenderTarget);
......
......@@ -20,8 +20,8 @@ class Renderer9;
class RenderTarget9 : public RenderTarget
{
public:
RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface);
RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples);
RenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
GLsizei samples);
virtual ~RenderTarget9();
static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget);
......@@ -34,8 +34,6 @@ class RenderTarget9 : public RenderTarget
DISALLOW_COPY_AND_ASSIGN(RenderTarget9);
IDirect3DSurface9 *mRenderTarget;
Renderer9 *mRenderer;
};
}
......
......@@ -1143,13 +1143,9 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
}
gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer)
gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer)
{
if (!depthbuffer)
{
ERR("Unexpected null depthbuffer for depth-only FBO.");
return NULL;
}
ASSERT(depthbuffer);
GLsizei width = depthbuffer->getWidth();
GLsizei height = depthbuffer->getHeight();
......@@ -1162,12 +1158,19 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme
mNullColorbufferCache[i].height == height)
{
mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
return mNullColorbufferCache[i].buffer;
*outColorBuffer = mNullColorbufferCache[i].buffer;
return gl::Error(GL_NO_ERROR);
}
}
gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0);
nullRenderbuffer->setStorage(width, height, GL_NONE, 0);
gl::Error error = nullRenderbuffer->setStorage(width, height, GL_NONE, 0);
if (error.isError())
{
SafeDelete(nullRenderbuffer);
return error;
}
gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer);
// add nullbuffer to the cache
......@@ -1186,7 +1189,8 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme
oldest->width = width;
oldest->height = height;
return nullbuffer;
*outColorBuffer = nullbuffer;
return gl::Error(GL_NO_ERROR);
}
gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
......@@ -1196,7 +1200,11 @@ gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0);
if (!attachment)
{
attachment = getNullColorbuffer(framebuffer->getDepthbuffer());
gl::Error error = getNullColorbuffer(framebuffer->getDepthbuffer(), &attachment);
if (error.isError())
{
return error;
}
}
ASSERT(attachment);
......@@ -2800,28 +2808,72 @@ gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y,
return gl::Error(GL_NO_ERROR);
}
RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
gl::Error Renderer9::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT)
{
SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
IDirect3DSurface9 *surface = NULL;
if (depth)
{
surface = swapChain9->getDepthStencil();
*outRT = new RenderTarget9(swapChain9->getDepthStencil(), swapChain9->GetDepthBufferInternalFormat(),
swapChain9->getWidth(), swapChain9->getHeight(), 1, 1);
}
else
{
surface = swapChain9->getRenderTarget();
*outRT = new RenderTarget9(swapChain9->getRenderTarget(), swapChain9->GetBackBufferInternalFormat(),
swapChain9->getWidth(), swapChain9->getHeight(), 1, 1);
}
RenderTarget9 *renderTarget = new RenderTarget9(this, surface);
return renderTarget;
return gl::Error(GL_NO_ERROR);
}
RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples)
gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT)
{
RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples);
return renderTarget;
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format);
GLuint supportedSamples = textureCaps.getNearestSamples(samples);
IDirect3DSurface9 *renderTarget = NULL;
if (width > 0 && height > 0)
{
bool requiresInitialization = false;
HRESULT result = D3DERR_INVALIDCALL;
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
{
result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat,
gl_d3d9::GetMultisampleType(supportedSamples),
0, FALSE, &renderTarget, NULL);
}
else
{
requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL);
result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
gl_d3d9::GetMultisampleType(supportedSamples),
0, FALSE, &renderTarget, NULL);
}
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result);
}
if (requiresInitialization)
{
// This format requires that the data be initialized before the render target can be used
// Unfortunately this requires a Get call on the d3d device but it is far better than having
// to mark the render target as lockable and copy data to the gpu.
IDirect3DSurface9 *prevRenderTarget = NULL;
mDevice->GetRenderTarget(0, &prevRenderTarget);
mDevice->SetRenderTarget(0, renderTarget);
mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
mDevice->SetRenderTarget(0, prevRenderTarget);
}
}
*outRT = new RenderTarget9(renderTarget, format, width, height, 1, supportedSamples);
return gl::Error(GL_NO_ERROR);
}
ShaderImpl *Renderer9::createShader(GLenum type)
......
......@@ -139,8 +139,8 @@ class Renderer9 : public RendererD3D
GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
// RenderTarget creation
virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples);
virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT);
virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT);
// Shader creation
virtual ShaderImpl *createShader(GLenum type);
......@@ -222,7 +222,7 @@ class Renderer9 : public RendererD3D
gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB);
gl::FramebufferAttachment *getNullColorbuffer(gl::FramebufferAttachment *depthbuffer);
gl::Error getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer);
D3DPOOL getBufferPool(DWORD usage) const;
......
......@@ -32,6 +32,9 @@ class SwapChain9 : public SwapChain
virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture();
EGLint getWidth() const { return mWidth; }
EGLint getHeight() const { return mHeight; }
static SwapChain9 *makeSwapChain9(SwapChain *swapChain);
private:
......
......@@ -25,6 +25,7 @@ TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
mMipLevels(0),
mTextureWidth(0),
mTextureHeight(0),
mInternalFormat(GL_NONE),
mTextureFormat(D3DFMT_UNKNOWN),
mRenderer(Renderer9::makeRenderer9(renderer)),
mD3DUsage(usage),
......@@ -105,6 +106,8 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain
mTexture = surfaceTexture;
mMipLevels = surfaceTexture->GetLevelCount();
mInternalFormat = swapchain->GetBackBufferInternalFormat();
D3DSURFACE_DESC surfaceDesc;
surfaceTexture->GetLevelDesc(0, &surfaceDesc);
mTextureWidth = surfaceDesc.Width;
......@@ -122,6 +125,8 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat
mTexture = NULL;
mRenderTarget = NULL;
mInternalFormat = internalformat;
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
mTextureFormat = d3dFormatInfo.texFormat;
......@@ -186,7 +191,7 @@ gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, R
return error;
}
mRenderTarget = new RenderTarget9(mRenderer, surface);
mRenderTarget = new RenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 1);
}
ASSERT(outRT);
......@@ -290,6 +295,8 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalfo
mRenderTarget[i] = NULL;
}
mInternalFormat = internalformat;
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
mTextureFormat = d3dFormatInfo.texFormat;
......@@ -364,7 +371,7 @@ gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, Ren
return error;
}
mRenderTarget[index.layerIndex] = new RenderTarget9(mRenderer, surface);
mRenderTarget[index.layerIndex] = new RenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 1);
}
*outRT = mRenderTarget[index.layerIndex];
......
......@@ -49,6 +49,7 @@ class TextureStorage9 : public TextureStorage
size_t mMipLevels;
size_t mTextureWidth;
size_t mTextureHeight;
GLenum mInternalFormat;
D3DFORMAT mTextureFormat;
Renderer9 *mRenderer;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment