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() ...@@ -38,15 +38,21 @@ Renderbuffer::~Renderbuffer()
SafeDelete(mRenderbuffer); 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; mWidth = width;
mHeight = height; mHeight = height;
mInternalFormat = internalformat; mInternalFormat = internalformat;
mSamples = samples; mSamples = samples;
mRenderbuffer->setStorage(width, height, internalformat, samples);
mActualFormat = mRenderbuffer->getActualFormat(); mActualFormat = mRenderbuffer->getActualFormat();
return Error(GL_NO_ERROR);
} }
rx::RenderbufferImpl *Renderbuffer::getImplementation() rx::RenderbufferImpl *Renderbuffer::getImplementation()
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "libGLESv2/Error.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/RefCountObject.h" #include "common/RefCountObject.h"
...@@ -36,7 +38,7 @@ class Renderbuffer : public RefCountObject ...@@ -36,7 +38,7 @@ class Renderbuffer : public RefCountObject
Renderbuffer(rx::RenderbufferImpl *impl, GLuint id); Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
virtual ~Renderbuffer(); 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(); rx::RenderbufferImpl *getImplementation();
......
...@@ -3881,7 +3881,12 @@ void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei sa ...@@ -3881,7 +3881,12 @@ void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei sa
} }
gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); 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 @@ ...@@ -11,6 +11,8 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "libGLESv2/Error.h"
#include "common/angleutils.h" #include "common/angleutils.h"
namespace rx namespace rx
...@@ -22,7 +24,7 @@ class RenderbufferImpl ...@@ -22,7 +24,7 @@ class RenderbufferImpl
RenderbufferImpl(); RenderbufferImpl();
virtual ~RenderbufferImpl() = 0; 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 getWidth() const = 0;
virtual GLsizei getHeight() const = 0; virtual GLsizei getHeight() const = 0;
......
...@@ -189,8 +189,8 @@ class Renderer ...@@ -189,8 +189,8 @@ class Renderer
GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0; GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0;
// RenderTarget creation // RenderTarget creation
virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0; virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) = 0;
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0; virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) = 0;
// Shader creation // Shader creation
virtual ShaderImpl *createShader(GLenum type) = 0; virtual ShaderImpl *createShader(GLenum type) = 0;
......
...@@ -39,6 +39,9 @@ class SwapChain ...@@ -39,6 +39,9 @@ class SwapChain
virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
virtual void recreate() = 0; virtual void recreate() = 0;
GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; }
GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; }
virtual HANDLE getShareHandle() {return mShareHandle;}; virtual HANDLE getShareHandle() {return mShareHandle;};
protected: protected:
......
...@@ -30,7 +30,7 @@ RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbu ...@@ -30,7 +30,7 @@ RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbu
return static_cast<RenderbufferD3D*>(renderbuffer); 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 // If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in // will expect one of the valid renderbuffer formats for use in
...@@ -42,16 +42,32 @@ void RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalf ...@@ -42,16 +42,32 @@ void RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalf
creationFormat = GL_DEPTH24_STENCIL8_OES; 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); SafeDelete(mRenderTarget);
mRenderTarget = newRT; 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); SafeDelete(mRenderTarget);
mRenderTarget = newRT; mRenderTarget = newRT;
return gl::Error(GL_NO_ERROR);
} }
GLsizei RenderbufferD3D::getWidth() const GLsizei RenderbufferD3D::getWidth() const
......
...@@ -28,8 +28,8 @@ class RenderbufferD3D : public RenderbufferImpl ...@@ -28,8 +28,8 @@ class RenderbufferD3D : public RenderbufferImpl
static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer); static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer);
virtual void setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) override;
void setStorage(SwapChain *swapChain, bool depth); gl::Error setStorage(SwapChain *swapChain, bool depth);
virtual GLsizei getWidth() const; virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const; virtual GLsizei getHeight() const;
......
...@@ -176,234 +176,90 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth ...@@ -176,234 +176,90 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth
return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
} }
RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, RenderTarget11::RenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) 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) if (mTexture)
{ {
mTexture->AddRef(); mTexture->AddRef();
} }
mRenderTarget = rtv;
if (mRenderTarget) if (mRenderTarget)
{ {
mRenderTarget->AddRef(); mRenderTarget->AddRef();
} }
mDepthStencil = NULL;
mShaderResource = srv;
if (mShaderResource) if (mShaderResource)
{ {
mShaderResource->AddRef(); mShaderResource->AddRef();
} }
mSubresourceIndex = 0; mWidth = width;
mHeight = height;
mDepth = depth;
mSamples = samples;
mInternalFormat = internalFormat;
mActualFormat = internalFormat;
if (mRenderTarget && mTexture) if (mRenderTarget && mTexture)
{ {
mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
D3D11_RENDER_TARGET_VIEW_DESC desc; D3D11_RENDER_TARGET_VIEW_DESC desc;
mRenderTarget->GetDesc(&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); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
mInternalFormat = dxgiFormatInfo.internalFormat;
mActualFormat = dxgiFormatInfo.internalFormat; mActualFormat = dxgiFormatInfo.internalFormat;
} }
} }
RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, RenderTarget11::RenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) 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) if (mTexture)
{ {
mTexture->AddRef(); mTexture->AddRef();
} }
mRenderTarget = NULL;
mDepthStencil = dsv;
if (mDepthStencil) if (mDepthStencil)
{ {
mDepthStencil->AddRef(); mDepthStencil->AddRef();
} }
mShaderResource = srv;
if (mShaderResource) if (mShaderResource)
{ {
mShaderResource->AddRef(); mShaderResource->AddRef();
} }
mSubresourceIndex = 0; mWidth = width;
mHeight = height;
mDepth = depth;
mSamples = samples;
mInternalFormat = internalFormat;
mActualFormat = internalFormat;
if (mDepthStencil && mTexture) if (mDepthStencil && mTexture)
{ {
mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
D3D11_DEPTH_STENCIL_VIEW_DESC desc; D3D11_DEPTH_STENCIL_VIEW_DESC desc;
mDepthStencil->GetDesc(&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); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
mInternalFormat = dxgiFormatInfo.internalFormat;
mActualFormat = 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() RenderTarget11::~RenderTarget11()
{ {
SafeRelease(mTexture); SafeRelease(mTexture);
......
...@@ -14,16 +14,15 @@ ...@@ -14,16 +14,15 @@
namespace rx namespace rx
{ {
class Renderer;
class Renderer11;
class RenderTarget11 : public RenderTarget class RenderTarget11 : public RenderTarget
{ {
public: public:
// RenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them // 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(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth); GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples);
RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples); RenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples);
virtual ~RenderTarget11(); virtual ~RenderTarget11();
static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget);
...@@ -45,8 +44,6 @@ class RenderTarget11 : public RenderTarget ...@@ -45,8 +44,6 @@ class RenderTarget11 : public RenderTarget
ID3D11RenderTargetView *mRenderTarget; ID3D11RenderTargetView *mRenderTarget;
ID3D11DepthStencilView *mDepthStencil; ID3D11DepthStencilView *mDepthStencil;
ID3D11ShaderResourceView *mShaderResource; ID3D11ShaderResourceView *mShaderResource;
Renderer11 *mRenderer;
}; };
} }
......
...@@ -2188,34 +2188,164 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView ...@@ -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); SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
RenderTarget11 *renderTarget = NULL;
if (depth) if (depth)
{ {
// Note: depth stencil may be NULL for 0 sized surfaces // Note: depth stencil may be NULL for 0 sized surfaces
renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), *outRT = new RenderTarget11(swapChain11->getDepthStencil(),
swapChain11->getDepthStencilTexture(), swapChain11->getDepthStencilTexture(),
swapChain11->getDepthStencilShaderResource(), swapChain11->getDepthStencilShaderResource(),
swapChain11->getWidth(), swapChain11->getHeight(), 1); swapChain11->GetDepthBufferInternalFormat(),
swapChain11->getWidth(), swapChain11->getHeight(), 1, 1);
} }
else else
{ {
// Note: render target may be NULL for 0 sized surfaces // Note: render target may be NULL for 0 sized surfaces
renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), *outRT = new RenderTarget11(swapChain11->getRenderTarget(),
swapChain11->getOffscreenTexture(), swapChain11->getOffscreenTexture(),
swapChain11->getRenderTargetShaderResource(), swapChain11->getRenderTargetShaderResource(),
swapChain11->getWidth(), swapChain11->getHeight(), 1); 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); const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format);
return renderTarget;
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) ShaderImpl *Renderer11::createShader(GLenum type)
......
...@@ -134,8 +134,8 @@ class Renderer11 : public RendererD3D ...@@ -134,8 +134,8 @@ class Renderer11 : public RendererD3D
GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
// RenderTarget creation // RenderTarget creation
virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT);
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT);
// Shader creation // Shader creation
virtual ShaderImpl *createShader(GLenum type); virtual ShaderImpl *createShader(GLenum type);
......
...@@ -65,6 +65,7 @@ TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) ...@@ -65,6 +65,7 @@ TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
: mBindFlags(bindFlags), : mBindFlags(bindFlags),
mTopLevel(0), mTopLevel(0),
mMipLevels(0), mMipLevels(0),
mInternalFormat(GL_NONE),
mTextureFormat(DXGI_FORMAT_UNKNOWN), mTextureFormat(DXGI_FORMAT_UNKNOWN),
mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
...@@ -561,6 +562,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch ...@@ -561,6 +562,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch
mTextureHeight = texDesc.Height; mTextureHeight = texDesc.Height;
mTextureDepth = 1; mTextureDepth = 1;
mInternalFormat = swapchain->GetBackBufferInternalFormat();
ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource();
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srv->GetDesc(&srvDesc); srv->GetDesc(&srvDesc);
...@@ -594,6 +597,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform ...@@ -594,6 +597,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform
mSwizzleRenderTargets[i] = NULL; mSwizzleRenderTargets[i] = NULL;
} }
mInternalFormat = internalformat;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
mTextureFormat = formatInfo.texFormat; mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat; mShaderResourceFormat = formatInfo.srvFormat;
...@@ -809,7 +814,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -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); 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 // RenderTarget will take ownership of these resources
SafeRelease(rtv); SafeRelease(rtv);
...@@ -833,7 +838,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -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); 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 // RenderTarget will take ownership of these resources
SafeRelease(dsv); SafeRelease(dsv);
...@@ -956,6 +961,8 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal ...@@ -956,6 +961,8 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal
} }
} }
mInternalFormat = internalformat;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
mTextureFormat = formatInfo.texFormat; mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat; mShaderResourceFormat = formatInfo.srvFormat;
...@@ -1210,7 +1217,7 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re ...@@ -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); 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 // RenderTarget will take ownership of these resources
SafeRelease(rtv); SafeRelease(rtv);
...@@ -1236,7 +1243,7 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re ...@@ -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); 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 // RenderTarget will take ownership of these resources
SafeRelease(dsv); SafeRelease(dsv);
...@@ -1374,6 +1381,8 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform ...@@ -1374,6 +1381,8 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform
mSwizzleRenderTargets[i] = NULL; mSwizzleRenderTargets[i] = NULL;
} }
mInternalFormat = internalformat;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
mTextureFormat = formatInfo.texFormat; mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat; mShaderResourceFormat = formatInfo.srvFormat;
...@@ -1617,7 +1626,7 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -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); 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 // RenderTarget will take ownership of these resources
SafeRelease(rtv); SafeRelease(rtv);
...@@ -1664,7 +1673,7 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -1664,7 +1673,7 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend
} }
ASSERT(SUCCEEDED(result)); 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 // RenderTarget will take ownership of these resources
SafeRelease(rtv); SafeRelease(rtv);
...@@ -1756,6 +1765,8 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in ...@@ -1756,6 +1765,8 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in
mSwizzleRenderTargets[level] = NULL; mSwizzleRenderTargets[level] = NULL;
} }
mInternalFormat = internalformat;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
mTextureFormat = formatInfo.texFormat; mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat; mShaderResourceFormat = formatInfo.srvFormat;
...@@ -2013,7 +2024,7 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, ...@@ -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); 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 // RenderTarget will take ownership of these resources
SafeRelease(rtv); SafeRelease(rtv);
......
...@@ -91,6 +91,7 @@ class TextureStorage11 : public TextureStorage ...@@ -91,6 +91,7 @@ class TextureStorage11 : public TextureStorage
int mTopLevel; int mTopLevel;
unsigned int mMipLevels; unsigned int mMipLevels;
GLenum mInternalFormat;
DXGI_FORMAT mTextureFormat; DXGI_FORMAT mTextureFormat;
DXGI_FORMAT mShaderResourceFormat; DXGI_FORMAT mShaderResourceFormat;
DXGI_FORMAT mRenderTargetFormat; DXGI_FORMAT mRenderTargetFormat;
......
...@@ -17,91 +17,27 @@ namespace rx ...@@ -17,91 +17,27 @@ namespace rx
{ {
// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. // 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); mWidth = width;
mRenderTarget = surface; mHeight = height;
mDepth = depth;
mSamples = samples;
mInternalFormat = internalFormat;
mActualFormat = internalFormat;
if (mRenderTarget) if (mRenderTarget)
{ {
D3DSURFACE_DESC description; D3DSURFACE_DESC description;
mRenderTarget->GetDesc(&description); mRenderTarget->GetDesc(&description);
mWidth = description.Width;
mHeight = description.Height;
mDepth = 1;
const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format); const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format);
mInternalFormat = d3dFormatInfo.internalFormat;
mActualFormat = 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() RenderTarget9::~RenderTarget9()
{ {
SafeRelease(mRenderTarget); SafeRelease(mRenderTarget);
......
...@@ -20,8 +20,8 @@ class Renderer9; ...@@ -20,8 +20,8 @@ class Renderer9;
class RenderTarget9 : public RenderTarget class RenderTarget9 : public RenderTarget
{ {
public: public:
RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface); RenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples); GLsizei samples);
virtual ~RenderTarget9(); virtual ~RenderTarget9();
static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget);
...@@ -34,8 +34,6 @@ class RenderTarget9 : public RenderTarget ...@@ -34,8 +34,6 @@ class RenderTarget9 : public RenderTarget
DISALLOW_COPY_AND_ASSIGN(RenderTarget9); DISALLOW_COPY_AND_ASSIGN(RenderTarget9);
IDirect3DSurface9 *mRenderTarget; IDirect3DSurface9 *mRenderTarget;
Renderer9 *mRenderer;
}; };
} }
......
...@@ -1143,13 +1143,9 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) ...@@ -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) ASSERT(depthbuffer);
{
ERR("Unexpected null depthbuffer for depth-only FBO.");
return NULL;
}
GLsizei width = depthbuffer->getWidth(); GLsizei width = depthbuffer->getWidth();
GLsizei height = depthbuffer->getHeight(); GLsizei height = depthbuffer->getHeight();
...@@ -1162,12 +1158,19 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme ...@@ -1162,12 +1158,19 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme
mNullColorbufferCache[i].height == height) mNullColorbufferCache[i].height == height)
{ {
mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; 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); 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); gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer);
// add nullbuffer to the cache // add nullbuffer to the cache
...@@ -1186,7 +1189,8 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme ...@@ -1186,7 +1189,8 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme
oldest->width = width; oldest->width = width;
oldest->height = height; oldest->height = height;
return nullbuffer; *outColorBuffer = nullbuffer;
return gl::Error(GL_NO_ERROR);
} }
gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
...@@ -1196,7 +1200,11 @@ gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) ...@@ -1196,7 +1200,11 @@ gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0); gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0);
if (!attachment) if (!attachment)
{ {
attachment = getNullColorbuffer(framebuffer->getDepthbuffer()); gl::Error error = getNullColorbuffer(framebuffer->getDepthbuffer(), &attachment);
if (error.isError())
{
return error;
}
} }
ASSERT(attachment); ASSERT(attachment);
...@@ -2800,28 +2808,72 @@ gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, ...@@ -2800,28 +2808,72 @@ gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y,
return gl::Error(GL_NO_ERROR); 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); SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
IDirect3DSurface9 *surface = NULL;
if (depth) if (depth)
{ {
surface = swapChain9->getDepthStencil(); *outRT = new RenderTarget9(swapChain9->getDepthStencil(), swapChain9->GetDepthBufferInternalFormat(),
swapChain9->getWidth(), swapChain9->getHeight(), 1, 1);
} }
else else
{ {
surface = swapChain9->getRenderTarget(); *outRT = new RenderTarget9(swapChain9->getRenderTarget(), swapChain9->GetBackBufferInternalFormat(),
swapChain9->getWidth(), swapChain9->getHeight(), 1, 1);
} }
RenderTarget9 *renderTarget = new RenderTarget9(this, surface); return gl::Error(GL_NO_ERROR);
return renderTarget;
} }
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); const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
return renderTarget;
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) ShaderImpl *Renderer9::createShader(GLenum type)
......
...@@ -139,8 +139,8 @@ class Renderer9 : public RendererD3D ...@@ -139,8 +139,8 @@ class Renderer9 : public RendererD3D
GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
// RenderTarget creation // RenderTarget creation
virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT);
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT);
// Shader creation // Shader creation
virtual ShaderImpl *createShader(GLenum type); virtual ShaderImpl *createShader(GLenum type);
...@@ -222,7 +222,7 @@ class Renderer9 : public RendererD3D ...@@ -222,7 +222,7 @@ class Renderer9 : public RendererD3D
gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB); 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; D3DPOOL getBufferPool(DWORD usage) const;
......
...@@ -32,6 +32,9 @@ class SwapChain9 : public SwapChain ...@@ -32,6 +32,9 @@ class SwapChain9 : public SwapChain
virtual IDirect3DSurface9 *getDepthStencil(); virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture(); virtual IDirect3DTexture9 *getOffscreenTexture();
EGLint getWidth() const { return mWidth; }
EGLint getHeight() const { return mHeight; }
static SwapChain9 *makeSwapChain9(SwapChain *swapChain); static SwapChain9 *makeSwapChain9(SwapChain *swapChain);
private: private:
......
...@@ -25,6 +25,7 @@ TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) ...@@ -25,6 +25,7 @@ TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
mMipLevels(0), mMipLevels(0),
mTextureWidth(0), mTextureWidth(0),
mTextureHeight(0), mTextureHeight(0),
mInternalFormat(GL_NONE),
mTextureFormat(D3DFMT_UNKNOWN), mTextureFormat(D3DFMT_UNKNOWN),
mRenderer(Renderer9::makeRenderer9(renderer)), mRenderer(Renderer9::makeRenderer9(renderer)),
mD3DUsage(usage), mD3DUsage(usage),
...@@ -105,6 +106,8 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain ...@@ -105,6 +106,8 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain
mTexture = surfaceTexture; mTexture = surfaceTexture;
mMipLevels = surfaceTexture->GetLevelCount(); mMipLevels = surfaceTexture->GetLevelCount();
mInternalFormat = swapchain->GetBackBufferInternalFormat();
D3DSURFACE_DESC surfaceDesc; D3DSURFACE_DESC surfaceDesc;
surfaceTexture->GetLevelDesc(0, &surfaceDesc); surfaceTexture->GetLevelDesc(0, &surfaceDesc);
mTextureWidth = surfaceDesc.Width; mTextureWidth = surfaceDesc.Width;
...@@ -122,6 +125,8 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat ...@@ -122,6 +125,8 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat
mTexture = NULL; mTexture = NULL;
mRenderTarget = NULL; mRenderTarget = NULL;
mInternalFormat = internalformat;
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
mTextureFormat = d3dFormatInfo.texFormat; mTextureFormat = d3dFormatInfo.texFormat;
...@@ -186,7 +191,7 @@ gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, R ...@@ -186,7 +191,7 @@ gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, R
return error; return error;
} }
mRenderTarget = new RenderTarget9(mRenderer, surface); mRenderTarget = new RenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 1);
} }
ASSERT(outRT); ASSERT(outRT);
...@@ -290,6 +295,8 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalfo ...@@ -290,6 +295,8 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalfo
mRenderTarget[i] = NULL; mRenderTarget[i] = NULL;
} }
mInternalFormat = internalformat;
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
mTextureFormat = d3dFormatInfo.texFormat; mTextureFormat = d3dFormatInfo.texFormat;
...@@ -364,7 +371,7 @@ gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, Ren ...@@ -364,7 +371,7 @@ gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, Ren
return error; return error;
} }
mRenderTarget[index.layerIndex] = new RenderTarget9(mRenderer, surface); mRenderTarget[index.layerIndex] = new RenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 1);
} }
*outRT = mRenderTarget[index.layerIndex]; *outRT = mRenderTarget[index.layerIndex];
......
...@@ -49,6 +49,7 @@ class TextureStorage9 : public TextureStorage ...@@ -49,6 +49,7 @@ class TextureStorage9 : public TextureStorage
size_t mMipLevels; size_t mMipLevels;
size_t mTextureWidth; size_t mTextureWidth;
size_t mTextureHeight; size_t mTextureHeight;
GLenum mInternalFormat;
D3DFORMAT mTextureFormat; D3DFORMAT mTextureFormat;
Renderer9 *mRenderer; 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