Changes the pointer from textures to their renderbuffer proxies to non-refcounted (2/2)

TRAC #19335 Issue=271 Instead, the texture maintains an internal refcount which causes the pointer to behave kind of like a "weak" shared pointer-- its reference won't prevent the renderbuffer from being deleted, but if the renderbuffer's refcount drops to zero, the texture should set its pointer to the renderbuffer to null so that a new one can be created at the next getRenderbuffer call. Signed-off-by: Nicolas Capens Signed-off-by: Daniel Koch git-svn-id: https://angleproject.googlecode.com/svn/trunk@948 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 0dc8a5ee
#define MAJOR_VERSION 1 #define MAJOR_VERSION 1
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 946 #define BUILD_REVISION 948
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -915,9 +915,9 @@ void Display::sync(bool block) ...@@ -915,9 +915,9 @@ void Display::sync(bool block)
freeEventQuery(query); freeEventQuery(query);
if (isDeviceLostError(result)) if (isDeviceLostError(result))
{ {
notifyDeviceLost(); notifyDeviceLost();
} }
} }
......
...@@ -22,6 +22,17 @@ RenderbufferInterface::RenderbufferInterface() ...@@ -22,6 +22,17 @@ RenderbufferInterface::RenderbufferInterface()
{ {
} }
// The default case for classes inherited from RenderbufferInterface is not to
// need to do anything upon the reference count to the parent Renderbuffer incrementing
// or decrementing.
void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy)
{
}
void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy)
{
}
GLuint RenderbufferInterface::getRedSize() const GLuint RenderbufferInterface::getRedSize() const
{ {
return dx2es::GetRedSize(getD3DFormat()); return dx2es::GetRedSize(getD3DFormat());
...@@ -62,6 +73,18 @@ RenderbufferTexture::~RenderbufferTexture() ...@@ -62,6 +73,18 @@ RenderbufferTexture::~RenderbufferTexture()
mTexture.set(NULL); mTexture.set(NULL);
} }
// Textures need to maintain their own reference count for references via
// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
void RenderbufferTexture::addProxyRef(const Renderbuffer *proxy)
{
mTexture->addProxyRef(proxy);
}
void RenderbufferTexture::releaseProxy(const Renderbuffer *proxy)
{
mTexture->releaseProxy(proxy);
}
IDirect3DSurface9 *RenderbufferTexture::getRenderTarget() IDirect3DSurface9 *RenderbufferTexture::getRenderTarget()
{ {
return mTexture->getRenderTarget(mTarget); return mTexture->getRenderTarget(mTarget);
...@@ -113,6 +136,22 @@ Renderbuffer::~Renderbuffer() ...@@ -113,6 +136,22 @@ Renderbuffer::~Renderbuffer()
delete mInstance; delete mInstance;
} }
// The RenderbufferInterface contained in this Renderbuffer may need to maintain
// its own reference count, so we pass it on here.
void Renderbuffer::addRef() const
{
mInstance->addProxyRef(this);
RefCountObject::addRef();
}
void Renderbuffer::release() const
{
mInstance->releaseProxy(this);
RefCountObject::release();
}
IDirect3DSurface9 *Renderbuffer::getRenderTarget() IDirect3DSurface9 *Renderbuffer::getRenderTarget()
{ {
return mInstance->getRenderTarget(); return mInstance->getRenderTarget();
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
namespace gl namespace gl
{ {
class Texture; class Texture;
class Renderbuffer;
class Colorbuffer; class Colorbuffer;
class DepthStencilbuffer; class DepthStencilbuffer;
...@@ -32,6 +33,9 @@ class RenderbufferInterface ...@@ -32,6 +33,9 @@ class RenderbufferInterface
virtual ~RenderbufferInterface() {}; virtual ~RenderbufferInterface() {};
virtual void addProxyRef(const Renderbuffer *proxy);
virtual void releaseProxy(const Renderbuffer *proxy);
virtual IDirect3DSurface9 *getRenderTarget() = 0; virtual IDirect3DSurface9 *getRenderTarget() = 0;
virtual IDirect3DSurface9 *getDepthStencil() = 0; virtual IDirect3DSurface9 *getDepthStencil() = 0;
...@@ -61,6 +65,9 @@ class RenderbufferTexture : public RenderbufferInterface ...@@ -61,6 +65,9 @@ class RenderbufferTexture : public RenderbufferInterface
virtual ~RenderbufferTexture(); virtual ~RenderbufferTexture();
void addProxyRef(const Renderbuffer *proxy);
void releaseProxy(const Renderbuffer *proxy);
IDirect3DSurface9 *getRenderTarget(); IDirect3DSurface9 *getRenderTarget();
IDirect3DSurface9 *getDepthStencil(); IDirect3DSurface9 *getDepthStencil();
...@@ -128,6 +135,13 @@ class Renderbuffer : public RefCountObject ...@@ -128,6 +135,13 @@ class Renderbuffer : public RefCountObject
virtual ~Renderbuffer(); virtual ~Renderbuffer();
// These functions from RefCountObject are overloaded here because
// Textures need to maintain their own count of references to them via
// Renderbuffers/RenderbufferTextures. These functions invoke those
// reference counting functions on the RenderbufferInterface.
void addRef() const;
void release() const;
IDirect3DSurface9 *getRenderTarget(); IDirect3DSurface9 *getRenderTarget();
IDirect3DSurface9 *getDepthStencil(); IDirect3DSurface9 *getDepthStencil();
......
...@@ -1722,11 +1722,13 @@ Texture2D::Texture2D(GLuint id) : Texture(id) ...@@ -1722,11 +1722,13 @@ Texture2D::Texture2D(GLuint id) : Texture(id)
{ {
mTexStorage = NULL; mTexStorage = NULL;
mSurface = NULL; mSurface = NULL;
mColorbufferProxy = NULL;
mProxyRefs = 0;
} }
Texture2D::~Texture2D() Texture2D::~Texture2D()
{ {
mColorbufferProxy.set(NULL); mColorbufferProxy = NULL;
delete mTexStorage; delete mTexStorage;
mTexStorage = NULL; mTexStorage = NULL;
...@@ -1738,6 +1740,23 @@ Texture2D::~Texture2D() ...@@ -1738,6 +1740,23 @@ Texture2D::~Texture2D()
} }
} }
// We need to maintain a count of references to renderbuffers acting as
// proxies for this texture, so that we do not attempt to use a pointer
// to a renderbuffer proxy which has been deleted.
void Texture2D::addProxyRef(const Renderbuffer *proxy)
{
mProxyRefs++;
}
void Texture2D::releaseProxy(const Renderbuffer *proxy)
{
if (mProxyRefs > 0)
mProxyRefs--;
if (mProxyRefs == 0)
mColorbufferProxy = NULL;
}
GLenum Texture2D::getTarget() const GLenum Texture2D::getTarget() const
{ {
return GL_TEXTURE_2D; return GL_TEXTURE_2D;
...@@ -2294,12 +2313,12 @@ Renderbuffer *Texture2D::getRenderbuffer(GLenum target) ...@@ -2294,12 +2313,12 @@ Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
} }
if (mColorbufferProxy.get() == NULL) if (mColorbufferProxy == NULL)
{ {
mColorbufferProxy.set(new Renderbuffer(id(), new RenderbufferTexture(this, target))); mColorbufferProxy = new Renderbuffer(id(), new RenderbufferTexture(this, target));
} }
return mColorbufferProxy.get(); return mColorbufferProxy;
} }
IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
...@@ -2383,19 +2402,53 @@ unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const ...@@ -2383,19 +2402,53 @@ unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const
TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id) TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
{ {
mTexStorage = NULL; mTexStorage = NULL;
for (int i = 0; i < 6; i++)
{
mFaceProxies[i] = NULL;
mFaceProxyRefs[i] = 0;
}
} }
TextureCubeMap::~TextureCubeMap() TextureCubeMap::~TextureCubeMap()
{ {
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
mFaceProxies[i].set(NULL); mFaceProxies[i] = NULL;
} }
delete mTexStorage; delete mTexStorage;
mTexStorage = NULL; mTexStorage = NULL;
} }
// We need to maintain a count of references to renderbuffers acting as
// proxies for this texture, so that the texture is not deleted while
// proxy references still exist. If the reference count drops to zero,
// we set our proxy pointer NULL, so that a new attempt at referencing
// will cause recreation.
void TextureCubeMap::addProxyRef(const Renderbuffer *proxy)
{
for (int i = 0; i < 6; i++)
{
if (mFaceProxies[i] == proxy)
mFaceProxyRefs[i]++;
}
}
void TextureCubeMap::releaseProxy(const Renderbuffer *proxy)
{
for (int i = 0; i < 6; i++)
{
if (mFaceProxies[i] == proxy)
{
if (mFaceProxyRefs[i] > 0)
mFaceProxyRefs[i]--;
if (mFaceProxyRefs[i] == 0)
mFaceProxies[i] = NULL;
}
}
}
GLenum TextureCubeMap::getTarget() const GLenum TextureCubeMap::getTarget() const
{ {
return GL_TEXTURE_CUBE_MAP; return GL_TEXTURE_CUBE_MAP;
...@@ -2995,12 +3048,12 @@ Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target) ...@@ -2995,12 +3048,12 @@ Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
unsigned int face = faceIndex(target); unsigned int face = faceIndex(target);
if (mFaceProxies[face].get() == NULL) if (mFaceProxies[face] == NULL)
{ {
mFaceProxies[face].set(new Renderbuffer(id(), new RenderbufferTexture(this, target))); mFaceProxies[face] = new Renderbuffer(id(), new RenderbufferTexture(this, target));
} }
return mFaceProxies[face].get(); return mFaceProxies[face];
} }
IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
......
...@@ -173,6 +173,9 @@ class Texture : public RefCountObject ...@@ -173,6 +173,9 @@ class Texture : public RefCountObject
virtual ~Texture(); virtual ~Texture();
virtual void addProxyRef(const Renderbuffer *proxy) = 0;
virtual void releaseProxy(const Renderbuffer *proxy) = 0;
virtual GLenum getTarget() const = 0; virtual GLenum getTarget() const = 0;
bool setMinFilter(GLenum filter); bool setMinFilter(GLenum filter);
...@@ -278,6 +281,9 @@ class Texture2D : public Texture ...@@ -278,6 +281,9 @@ class Texture2D : public Texture
~Texture2D(); ~Texture2D();
void addProxyRef(const Renderbuffer *proxy);
void releaseProxy(const Renderbuffer *proxy);
virtual GLenum getTarget() const; virtual GLenum getTarget() const;
virtual GLsizei getWidth(GLint level) const; virtual GLsizei getWidth(GLint level) const;
...@@ -323,7 +329,13 @@ class Texture2D : public Texture ...@@ -323,7 +329,13 @@ class Texture2D : public Texture
TextureStorage2D *mTexStorage; TextureStorage2D *mTexStorage;
egl::Surface *mSurface; egl::Surface *mSurface;
BindingPointer<Renderbuffer> mColorbufferProxy; // A specific internal reference count is kept for colorbuffer proxy references,
// because, as the renderbuffer acting as proxy will maintain a binding pointer
// back to this texture, there would be a circular reference if we used a binding
// pointer here. This reference count will cause the pointer to be set to NULL if
// the count drops to zero, but will not cause deletion of the Renderbuffer.
Renderbuffer *mColorbufferProxy;
unsigned int mProxyRefs;
}; };
class TextureStorageCubeMap : public TextureStorage class TextureStorageCubeMap : public TextureStorage
...@@ -352,6 +364,9 @@ class TextureCubeMap : public Texture ...@@ -352,6 +364,9 @@ class TextureCubeMap : public Texture
~TextureCubeMap(); ~TextureCubeMap();
void addProxyRef(const Renderbuffer *proxy);
void releaseProxy(const Renderbuffer *proxy);
virtual GLenum getTarget() const; virtual GLenum getTarget() const;
virtual GLsizei getWidth(GLint level) const; virtual GLsizei getWidth(GLint level) const;
...@@ -405,7 +420,13 @@ class TextureCubeMap : public Texture ...@@ -405,7 +420,13 @@ class TextureCubeMap : public Texture
TextureStorageCubeMap *mTexStorage; TextureStorageCubeMap *mTexStorage;
BindingPointer<Renderbuffer> mFaceProxies[6]; // A specific internal reference count is kept for colorbuffer proxy references,
// because, as the renderbuffer acting as proxy will maintain a binding pointer
// back to this texture, there would be a circular reference if we used a binding
// pointer here. This reference count will cause the pointer to be set to NULL if
// the count drops to zero, but will not cause deletion of the Renderbuffer.
Renderbuffer *mFaceProxies[6];
unsigned int *mFaceProxyRefs[6];
}; };
} }
......
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