Commit 6c1f671b by Jamie Madill Committed by Commit Bot

Add destroy hooks for several GL objects.

These hooks allow the back-end renderer to free object resources without having to store pointers to shared device handles for each and every object. This will allow us to save memory on back-ends that really care about memory overhead. There is a downside in that there is more boilerplate in passing gl::Context handles around everywhere. BUG=angleproject:1684 Change-Id: I89463bba8d23f92920e8956650cb73c7fc6d66b7 Reviewed-on: https://chromium-review.googlesource.com/426401 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent abf38572
......@@ -44,6 +44,13 @@ Buffer::~Buffer()
SafeDelete(mImpl);
}
void Buffer::destroy(const Context *context)
{
// In tests, mImpl might be null.
if (mImpl)
mImpl->destroy(rx::SafeGetImpl(context));
}
void Buffer::setLabel(const std::string &label)
{
mState.mLabel = label;
......
......@@ -65,6 +65,7 @@ class Buffer final : public RefCountObject, public LabeledObject
public:
Buffer(rx::GLImplFactory *factory, GLuint id);
~Buffer() override;
void destroy(const Context *context) override;
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
......
......@@ -385,7 +385,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
void Context::destroy(egl::Display *display)
{
mGLState.reset();
mGLState.reset(this);
for (auto fence : mFenceNVMap)
{
......@@ -409,7 +409,7 @@ void Context::destroy(egl::Display *display)
{
if (transformFeedback.second != nullptr)
{
transformFeedback.second->release();
transformFeedback.second->release(this);
}
}
......@@ -424,6 +424,15 @@ void Context::destroy(egl::Display *display)
releaseSurface(display);
SafeDelete(mCompiler);
mState.mBuffers->release(this);
mState.mShaderPrograms->release(this);
mState.mTextures->release(this);
mState.mRenderbuffers->release(this);
mState.mSamplers->release(this);
mState.mFenceSyncs->release(this);
mState.mPaths->release(this);
mState.mFramebuffers->release(this);
}
Context::~Context()
......@@ -616,17 +625,17 @@ void Context::deleteBuffer(GLuint buffer)
detachBuffer(buffer);
}
mState.mBuffers->deleteObject(buffer);
mState.mBuffers->deleteObject(this, buffer);
}
void Context::deleteShader(GLuint shader)
{
mState.mShaderPrograms->deleteShader(shader);
mState.mShaderPrograms->deleteShader(this, shader);
}
void Context::deleteProgram(GLuint program)
{
mState.mShaderPrograms->deleteProgram(program);
mState.mShaderPrograms->deleteProgram(this, program);
}
void Context::deleteTexture(GLuint texture)
......@@ -636,7 +645,7 @@ void Context::deleteTexture(GLuint texture)
detachTexture(texture);
}
mState.mTextures->deleteObject(texture);
mState.mTextures->deleteObject(this, texture);
}
void Context::deleteRenderbuffer(GLuint renderbuffer)
......@@ -646,7 +655,7 @@ void Context::deleteRenderbuffer(GLuint renderbuffer)
detachRenderbuffer(renderbuffer);
}
mState.mRenderbuffers->deleteObject(renderbuffer);
mState.mRenderbuffers->deleteObject(this, renderbuffer);
}
void Context::deleteFenceSync(GLsync fenceSync)
......@@ -655,7 +664,8 @@ void Context::deleteFenceSync(GLsync fenceSync)
// wait commands finish. However, since the name becomes invalid, we cannot query the fence,
// and since our API is currently designed for being called from a single thread, we can delete
// the fence immediately.
mState.mFenceSyncs->deleteObject(static_cast<GLuint>(reinterpret_cast<uintptr_t>(fenceSync)));
mState.mFenceSyncs->deleteObject(this,
static_cast<GLuint>(reinterpret_cast<uintptr_t>(fenceSync)));
}
void Context::deletePaths(GLuint first, GLsizei range)
......@@ -772,7 +782,7 @@ void Context::deleteSampler(GLuint sampler)
detachSampler(sampler);
}
mState.mSamplers->deleteObject(sampler);
mState.mSamplers->deleteObject(this, sampler);
}
void Context::deleteTransformFeedback(GLuint transformFeedback)
......@@ -784,7 +794,7 @@ void Context::deleteTransformFeedback(GLuint transformFeedback)
if (transformFeedbackObject != nullptr)
{
detachTransformFeedback(transformFeedback);
transformFeedbackObject->release();
transformFeedbackObject->release(this);
}
mTransformFeedbackMap.erase(iter);
......@@ -799,7 +809,7 @@ void Context::deleteFramebuffer(GLuint framebuffer)
detachFramebuffer(framebuffer);
}
mState.mFramebuffers->deleteObject(framebuffer);
mState.mFramebuffers->deleteObject(this, framebuffer);
}
void Context::deleteFenceNV(GLuint fence)
......@@ -1068,7 +1078,7 @@ void Context::bindPixelUnpackBuffer(GLuint bufferHandle)
void Context::useProgram(GLuint program)
{
mGLState.setProgram(getProgram(program));
mGLState.setProgram(this, getProgram(program));
}
void Context::bindTransformFeedback(GLuint transformFeedbackHandle)
......@@ -2378,7 +2388,7 @@ void Context::beginTransformFeedback(GLenum primitiveMode)
ASSERT(transformFeedback != nullptr);
ASSERT(!transformFeedback->isPaused());
transformFeedback->begin(primitiveMode, mGLState.getProgram());
transformFeedback->begin(this, primitiveMode, mGLState.getProgram());
}
bool Context::hasActiveTransformFeedback(GLuint program) const
......
......@@ -95,14 +95,7 @@ ContextState::ContextState(uintptr_t contextIn,
ContextState::~ContextState()
{
mBuffers->release();
mShaderPrograms->release();
mTextures->release();
mRenderbuffers->release();
mSamplers->release();
mFenceSyncs->release();
mPaths->release();
mFramebuffers->release();
// Handles are released by the Context.
}
const TextureCaps &ContextState::getTextureCap(GLenum internalFormat) const
......
......@@ -646,6 +646,7 @@ Error Display::createContext(const Config *configuration, gl::Context *shareCont
ANGLE_TRY(restoreLostDevice());
}
// This display texture sharing will allow the first context to create the texture share group.
bool usingDisplayTextureShareGroup =
attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
gl::TextureManager *shareTextures = nullptr;
......@@ -748,7 +749,7 @@ void Display::destroyContext(gl::Context *context)
{
// If this is the last context using the global share group, destroy the global texture
// manager so that the textures can be destroyed while a context still exists
mTextureManager->release();
mTextureManager->release(context);
mTextureManager = nullptr;
}
mGlobalTextureShareGroupUsers--;
......
......@@ -178,6 +178,6 @@ class Display final : angle::NonCopyable
size_t mGlobalTextureShareGroupUsers;
};
}
} // namespace egl
#endif // LIBANGLE_DISPLAY_H_
......@@ -54,6 +54,8 @@ class FenceSync final : public RefCountObject, public LabeledObject
FenceSync(rx::FenceSyncImpl *impl, GLuint id);
virtual ~FenceSync();
void destroy(const Context *context) override {}
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
......
......@@ -14,6 +14,7 @@
#include "common/utilities.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/Surface.h"
......@@ -322,6 +323,16 @@ Framebuffer::~Framebuffer()
SafeDelete(mImpl);
}
void Framebuffer::destroy(const Context *context)
{
mImpl->destroy(rx::SafeGetImpl(context));
}
void Framebuffer::destroyDefault(const egl::Display *display)
{
mImpl->destroyDefault(rx::SafeGetImpl(display));
}
void Framebuffer::setLabel(const std::string &label)
{
mState.mLabel = label;
......
......@@ -32,6 +32,7 @@ class SurfaceImpl;
namespace egl
{
class Display;
class Surface;
}
......@@ -107,6 +108,8 @@ class Framebuffer final : public LabeledObject, public angle::SignalReceiver
Framebuffer(rx::GLImplFactory *factory);
virtual ~Framebuffer();
void destroy(const Context *context);
void destroyDefault(const egl::Display *display);
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
......
......@@ -254,20 +254,7 @@ ProgramState::ProgramState()
ProgramState::~ProgramState()
{
if (mAttachedVertexShader != nullptr)
{
mAttachedVertexShader->release();
}
if (mAttachedFragmentShader != nullptr)
{
mAttachedFragmentShader->release();
}
if (mAttachedComputeShader != nullptr)
{
mAttachedComputeShader->release();
}
ASSERT(!mAttachedVertexShader && !mAttachedFragmentShader && !mAttachedComputeShader);
}
const std::string &ProgramState::getLabel()
......@@ -397,11 +384,34 @@ Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLui
Program::~Program()
{
unlink(true);
ASSERT(!mState.mAttachedVertexShader && !mState.mAttachedFragmentShader &&
!mState.mAttachedComputeShader);
SafeDelete(mProgram);
}
void Program::destroy(const Context *context)
{
if (mState.mAttachedVertexShader != nullptr)
{
mState.mAttachedVertexShader->release(context);
mState.mAttachedVertexShader = nullptr;
}
if (mState.mAttachedFragmentShader != nullptr)
{
mState.mAttachedFragmentShader->release(context);
mState.mAttachedFragmentShader = nullptr;
}
if (mState.mAttachedComputeShader != nullptr)
{
mState.mAttachedComputeShader->release(context);
mState.mAttachedComputeShader = nullptr;
}
mProgram->destroy(rx::SafeGetImpl(context));
}
void Program::setLabel(const std::string &label)
{
mState.mLabel = label;
......@@ -442,7 +452,7 @@ void Program::attachShader(Shader *shader)
}
}
bool Program::detachShader(Shader *shader)
bool Program::detachShader(const Context *context, Shader *shader)
{
switch (shader->getType())
{
......@@ -453,7 +463,7 @@ bool Program::detachShader(Shader *shader)
return false;
}
shader->release();
shader->release(context);
mState.mAttachedVertexShader = nullptr;
break;
}
......@@ -464,7 +474,7 @@ bool Program::detachShader(Shader *shader)
return false;
}
shader->release();
shader->release(context);
mState.mAttachedFragmentShader = nullptr;
break;
}
......@@ -475,7 +485,7 @@ bool Program::detachShader(Shader *shader)
return false;
}
shader->release();
shader->release(context);
mState.mAttachedComputeShader = nullptr;
break;
}
......@@ -586,7 +596,7 @@ Error Program::link(const gl::Context *context)
{
const auto &data = context->getContextState();
unlink(false);
unlink();
mInfoLog.reset();
resetUniformBlockBindings();
......@@ -724,29 +734,8 @@ Error Program::link(const gl::Context *context)
}
// Returns the program object to an unlinked state, before re-linking, or at destruction
void Program::unlink(bool destroy)
void Program::unlink()
{
if (destroy) // Object being destructed
{
if (mState.mAttachedFragmentShader)
{
mState.mAttachedFragmentShader->release();
mState.mAttachedFragmentShader = nullptr;
}
if (mState.mAttachedVertexShader)
{
mState.mAttachedVertexShader->release();
mState.mAttachedVertexShader = nullptr;
}
if (mState.mAttachedComputeShader)
{
mState.mAttachedComputeShader->release();
mState.mAttachedComputeShader = nullptr;
}
}
mState.mAttributes.clear();
mState.mActiveAttribLocationsMask.reset();
mState.mTransformFeedbackVaryingVars.clear();
......@@ -772,7 +761,7 @@ Error Program::loadBinary(const Context *context,
const void *binary,
GLsizei length)
{
unlink(false);
unlink();
#if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
return NoError();
......@@ -1103,13 +1092,13 @@ bool Program::getBinaryRetrievableHint() const
return mState.mBinaryRetrieveableHint;
}
void Program::release()
void Program::release(const Context *context)
{
mRefCount--;
if (mRefCount == 0 && mDeleteStatus)
{
mResourceManager->deleteProgram(mHandle);
mResourceManager->deleteProgram(context, mHandle);
}
}
......
......@@ -263,6 +263,7 @@ class Program final : angle::NonCopyable, public LabeledObject
public:
Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle);
~Program();
void destroy(const Context *context);
GLuint id() const { return mHandle; }
......@@ -272,7 +273,7 @@ class Program final : angle::NonCopyable, public LabeledObject
rx::ProgramImpl *getImplementation() const { return mProgram; }
void attachShader(Shader *shader);
bool detachShader(Shader *shader);
bool detachShader(const Context *context, Shader *shader);
int getAttachedShadersCount() const;
const Shader *getAttachedVertexShader() const { return mState.mAttachedVertexShader; }
......@@ -384,7 +385,7 @@ class Program final : angle::NonCopyable, public LabeledObject
static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
void addRef();
void release();
void release(const Context *context);
unsigned int getRefCount() const;
void flagForDeletion();
bool isFlaggedForDeletion() const;
......@@ -430,7 +431,7 @@ class Program final : angle::NonCopyable, public LabeledObject
using MergedVaryings = std::map<std::string, VaryingRef>;
void unlink(bool destroy = false);
void unlink();
void resetUniformBlockBindings();
bool linkAttributes(const ContextState &data, InfoLog &infoLog);
......
......@@ -18,6 +18,11 @@
#include <cstddef>
namespace gl
{
class Context;
}
class RefCountObjectNoID : angle::NonCopyable
{
public:
......@@ -35,10 +40,22 @@ class RefCountObjectNoID : angle::NonCopyable
}
}
// A specialized release method for objects which need a destroy context.
void release(const gl::Context *context)
{
ASSERT(mRefCount > 0);
if (--mRefCount == 0)
{
destroy(context);
delete this;
}
}
size_t getRefCount() const { return mRefCount; }
protected:
virtual ~RefCountObjectNoID() { ASSERT(mRefCount == 0); }
virtual void destroy(const gl::Context *context) {}
private:
mutable std::size_t mRefCount;
......
......@@ -35,6 +35,8 @@ class Renderbuffer final : public egl::ImageSibling,
Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
virtual ~Renderbuffer();
void destroy(const Context *context) override {}
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
......
......@@ -54,10 +54,11 @@ void ResourceManagerBase<HandleAllocatorType>::addRef()
}
template <typename HandleAllocatorType>
void ResourceManagerBase<HandleAllocatorType>::release()
void ResourceManagerBase<HandleAllocatorType>::release(const Context *context)
{
if (--mRefCount == 0)
{
reset(context);
delete this;
}
}
......@@ -65,14 +66,23 @@ void ResourceManagerBase<HandleAllocatorType>::release()
template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::~TypedResourceManager()
{
ASSERT(mObjectMap.empty());
}
template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::reset(const Context *context)
{
while (!mObjectMap.empty())
{
deleteObject(mObjectMap.begin()->first);
deleteObject(context, mObjectMap.begin()->first);
}
mObjectMap.clear();
}
template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObject(GLuint handle)
void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObject(
const Context *context,
GLuint handle)
{
auto objectIter = mObjectMap.find(handle);
if (objectIter == mObjectMap.end())
......@@ -82,6 +92,7 @@ void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObjec
if (objectIter->second != nullptr)
{
objectIter->second->destroy(context);
ImplT::DeleteObject(objectIter->second);
}
......@@ -181,14 +192,22 @@ bool BufferManager::isBufferGenerated(GLuint buffer) const
ShaderProgramManager::~ShaderProgramManager()
{
ASSERT(mPrograms.empty());
ASSERT(mShaders.empty());
}
void ShaderProgramManager::reset(const Context *context)
{
while (!mPrograms.empty())
{
deleteProgram(mPrograms.begin()->first);
deleteProgram(context, mPrograms.begin()->first);
}
mPrograms.clear();
while (!mShaders.empty())
{
deleteShader(mShaders.begin()->first);
deleteShader(context, mShaders.begin()->first);
}
mShaders.clear();
}
GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
......@@ -201,9 +220,9 @@ GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
return handle;
}
void ShaderProgramManager::deleteShader(GLuint shader)
void ShaderProgramManager::deleteShader(const Context *context, GLuint shader)
{
deleteObject(&mShaders, shader);
deleteObject(context, &mShaders, shader);
}
Shader *ShaderProgramManager::getShader(GLuint handle) const
......@@ -218,9 +237,9 @@ GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
return handle;
}
void ShaderProgramManager::deleteProgram(GLuint program)
void ShaderProgramManager::deleteProgram(const gl::Context *context, GLuint program)
{
deleteObject(&mPrograms, program);
deleteObject(context, &mPrograms, program);
}
Program *ShaderProgramManager::getProgram(GLuint handle) const
......@@ -229,7 +248,9 @@ Program *ShaderProgramManager::getProgram(GLuint handle) const
}
template <typename ObjectType>
void ShaderProgramManager::deleteObject(ResourceMap<ObjectType> *objectMap, GLuint id)
void ShaderProgramManager::deleteObject(const Context *context,
ResourceMap<ObjectType> *objectMap,
GLuint id)
{
auto iter = objectMap->find(id);
if (iter == objectMap->end())
......@@ -241,6 +262,7 @@ void ShaderProgramManager::deleteObject(ResourceMap<ObjectType> *objectMap, GLui
if (object->getRefCount() == 0)
{
mHandleAllocator.release(id);
object->destroy(context);
SafeDelete(object);
objectMap->erase(iter);
}
......@@ -421,10 +443,16 @@ bool PathManager::hasPath(GLuint handle) const
PathManager::~PathManager()
{
ASSERT(mPaths.empty());
}
void PathManager::reset(const Context *context)
{
for (auto path : mPaths)
{
SafeDelete(path.second);
}
mPaths.clear();
}
// FramebufferManager Implementation.
......
......@@ -26,6 +26,7 @@ namespace gl
{
class Buffer;
struct Caps;
class Context;
class FenceSync;
class Framebuffer;
struct Limitations;
......@@ -43,9 +44,10 @@ class ResourceManagerBase : angle::NonCopyable
ResourceManagerBase();
void addRef();
void release();
void release(const Context *context);
protected:
virtual void reset(const Context *context) = 0;
virtual ~ResourceManagerBase() {}
HandleAllocatorType mHandleAllocator;
......@@ -60,7 +62,7 @@ class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType>
public:
TypedResourceManager() {}
void deleteObject(GLuint handle);
void deleteObject(const Context *context, GLuint handle);
protected:
~TypedResourceManager() override;
......@@ -90,6 +92,8 @@ class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType>
GLuint handle,
ArgTypes... args);
void reset(const Context *context) override;
ResourceMap<ResourceType> mObjectMap;
};
......@@ -117,13 +121,13 @@ class ShaderProgramManager : public ResourceManagerBase<HandleAllocator>
{
public:
GLuint createShader(rx::GLImplFactory *factory,
const gl::Limitations &rendererLimitations,
const Limitations &rendererLimitations,
GLenum type);
void deleteShader(GLuint shader);
void deleteShader(const Context *context, GLuint shader);
Shader *getShader(GLuint handle) const;
GLuint createProgram(rx::GLImplFactory *factory);
void deleteProgram(GLuint program);
void deleteProgram(const Context *context, GLuint program);
Program *getProgram(GLuint handle) const;
protected:
......@@ -131,7 +135,9 @@ class ShaderProgramManager : public ResourceManagerBase<HandleAllocator>
private:
template <typename ObjectType>
void deleteObject(ResourceMap<ObjectType> *objectMap, GLuint id);
void deleteObject(const Context *context, ResourceMap<ObjectType> *objectMap, GLuint id);
void reset(const Context *context) override;
ResourceMap<Shader> mShaders;
ResourceMap<Program> mPrograms;
......@@ -217,6 +223,7 @@ class PathManager : public ResourceManagerBase<HandleRangeAllocator>
protected:
~PathManager() override;
void reset(const Context *context) override;
private:
ResourceMap<Path> mPaths;
......
......@@ -32,9 +32,9 @@ class ResourceManagerTest : public testing::Test
void TearDown() override
{
mTextureManager->release();
mBufferManager->release();
mRenderbuffermanager->release();
mTextureManager->release(nullptr);
mBufferManager->release(nullptr);
mRenderbuffermanager->release(nullptr);
}
MockGLFactory mMockFactory;
......
......@@ -29,6 +29,8 @@ class Sampler final : public RefCountObject, public LabeledObject
Sampler(rx::GLImplFactory *factory, GLuint id);
~Sampler() override;
void destroy(const Context *context) override {}
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
......
......@@ -352,13 +352,13 @@ void Shader::addRef()
mRefCount++;
}
void Shader::release()
void Shader::release(const Context *context)
{
mRefCount--;
if (mRefCount == 0 && mDeleteStatus)
{
mResourceManager->deleteShader(mHandle);
mResourceManager->deleteShader(context, mHandle);
}
}
......
......@@ -89,6 +89,7 @@ class Shader final : angle::NonCopyable, public LabeledObject
GLenum type,
GLuint handle);
void destroy(const Context *context) {}
virtual ~Shader();
void setLabel(const std::string &label) override;
......@@ -115,7 +116,7 @@ class Shader final : angle::NonCopyable, public LabeledObject
bool isCompiled() const { return mCompiled; }
void addRef();
void release();
void release(const Context *context);
unsigned int getRefCount() const;
bool isFlaggedForDeletion() const;
void flagForDeletion();
......
......@@ -67,7 +67,6 @@ State::State()
State::~State()
{
reset();
}
void State::initialize(const Caps &caps,
......@@ -212,7 +211,7 @@ void State::initialize(const Caps &caps,
mPathStencilMask = std::numeric_limits<GLuint>::max();
}
void State::reset()
void State::reset(const Context *context)
{
for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
{
......@@ -233,7 +232,7 @@ void State::reset()
if (mProgram)
{
mProgram->release();
mProgram->release(context);
}
mProgram = NULL;
......@@ -1018,13 +1017,13 @@ bool State::removeVertexArrayBinding(GLuint vertexArray)
return false;
}
void State::setProgram(Program *newProgram)
void State::setProgram(const Context *context, Program *newProgram)
{
if (mProgram != newProgram)
{
if (mProgram)
{
mProgram->release();
mProgram->release(context);
}
mProgram = newProgram;
......
......@@ -45,7 +45,7 @@ class State : angle::NonCopyable
const Version &clientVersion,
bool debug,
bool bindGeneratesResource);
void reset();
void reset(const Context *context);
// State chunk getters
const RasterizerState &getRasterizerState() const;
......@@ -194,7 +194,7 @@ class State : angle::NonCopyable
bool removeVertexArrayBinding(GLuint vertexArray);
// Program binding manipulation
void setProgram(Program *newProgram);
void setProgram(const Context *context, Program *newProgram);
Program *getProgram() const;
// Transform feedback object (not buffer) binding manipulation
......
......@@ -89,6 +89,19 @@ Surface::~Surface()
SafeDelete(mImplementation);
}
void Surface::destroy(const Display *display)
{
if (mState.defaultFramebuffer)
{
mState.defaultFramebuffer->destroyDefault(display);
}
if (mImplementation)
{
mImplementation->destroy(rx::SafeGetImpl(display));
}
delete this;
}
Error Surface::initialize(const Display &display)
{
ANGLE_TRY(mImplementation->initialize(display.getImplementation()));
......@@ -116,11 +129,7 @@ void Surface::setIsCurrent(Display *display, bool isCurrent)
mCurrentCount--;
if (mCurrentCount == 0 && mDestroyed)
{
if (mImplementation)
{
mImplementation->destroy(rx::SafeGetImpl(display));
}
delete this;
destroy(display);
}
}
......@@ -129,11 +138,7 @@ void Surface::onDestroy(Display *display)
mDestroyed = true;
if (mCurrentCount == 0)
{
if (mImplementation)
{
mImplementation->destroy(rx::SafeGetImpl(display));
}
delete this;
destroy(display);
}
}
......
......@@ -141,6 +141,9 @@ class Surface : public gl::FramebufferAttachmentObject
gl::Format mBackFormat;
gl::Format mDSFormat;
private:
void destroy(const egl::Display *display);
};
class WindowSurface final : public Surface
......
......@@ -184,6 +184,8 @@ class Texture final : public egl::ImageSibling,
Texture(rx::GLImplFactory *factory, GLuint id, GLenum target);
~Texture() override;
void destroy(const Context *context) override {}
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
......
......@@ -50,13 +50,18 @@ TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory, GLuint id,
ASSERT(mImplementation != nullptr);
}
TransformFeedback::~TransformFeedback()
void TransformFeedback::destroy(const Context *context)
{
if (mState.mProgram)
{
mState.mProgram->release();
mState.mProgram->release(context);
mState.mProgram = nullptr;
}
}
TransformFeedback::~TransformFeedback()
{
ASSERT(!mState.mProgram);
mState.mGenericBuffer.set(nullptr);
for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
{
......@@ -76,16 +81,16 @@ const std::string &TransformFeedback::getLabel() const
return mState.mLabel;
}
void TransformFeedback::begin(GLenum primitiveMode, Program *program)
void TransformFeedback::begin(const Context *context, GLenum primitiveMode, Program *program)
{
mState.mActive = true;
mState.mPrimitiveMode = primitiveMode;
mState.mPaused = false;
mImplementation->begin(primitiveMode);
bindProgram(program);
bindProgram(context, program);
}
void TransformFeedback::end()
void TransformFeedback::end(const Context *context)
{
mState.mActive = false;
mState.mPrimitiveMode = GL_NONE;
......@@ -93,7 +98,7 @@ void TransformFeedback::end()
mImplementation->end();
if (mState.mProgram)
{
mState.mProgram->release();
mState.mProgram->release(context);
mState.mProgram = nullptr;
}
}
......@@ -125,13 +130,13 @@ GLenum TransformFeedback::getPrimitiveMode() const
return mState.mPrimitiveMode;
}
void TransformFeedback::bindProgram(Program *program)
void TransformFeedback::bindProgram(const Context *context, Program *program)
{
if (mState.mProgram != program)
{
if (mState.mProgram != nullptr)
{
mState.mProgram->release();
mState.mProgram->release(context);
}
mState.mProgram = program;
if (mState.mProgram != nullptr)
......
......@@ -24,6 +24,7 @@ namespace gl
{
class Buffer;
struct Caps;
class Context;
class Program;
class TransformFeedbackState final : public angle::NonCopyable
......@@ -55,12 +56,13 @@ class TransformFeedback final : public RefCountObject, public LabeledObject
public:
TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps);
virtual ~TransformFeedback();
void destroy(const Context *context) override;
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
void begin(GLenum primitiveMode, Program *program);
void end();
void begin(const Context *context, GLenum primitiveMode, Program *program);
void end(const Context *context);
void pause();
void resume();
......@@ -83,7 +85,7 @@ class TransformFeedback final : public RefCountObject, public LabeledObject
const rx::TransformFeedbackImpl *getImplementation() const;
private:
void bindProgram(Program *program);
void bindProgram(const Context *context, Program *program);
TransformFeedbackState mState;
rx::TransformFeedbackImpl* mImplementation;
......
......@@ -72,11 +72,11 @@ TEST_F(TransformFeedbackTest, SideEffectsOfStartAndStop)
EXPECT_FALSE(mFeedback->isActive());
EXPECT_CALL(*mImpl, begin(GL_TRIANGLES));
mFeedback->begin(GL_TRIANGLES, nullptr);
mFeedback->begin(nullptr, GL_TRIANGLES, nullptr);
EXPECT_TRUE(mFeedback->isActive());
EXPECT_EQ(static_cast<GLenum>(GL_TRIANGLES), mFeedback->getPrimitiveMode());
EXPECT_CALL(*mImpl, end());
mFeedback->end();
mFeedback->end(nullptr);
EXPECT_FALSE(mFeedback->isActive());
}
......@@ -86,7 +86,7 @@ TEST_F(TransformFeedbackTest, SideEffectsOfPauseAndResume)
EXPECT_FALSE(mFeedback->isActive());
EXPECT_CALL(*mImpl, begin(GL_TRIANGLES));
mFeedback->begin(GL_TRIANGLES, nullptr);
mFeedback->begin(nullptr, GL_TRIANGLES, nullptr);
EXPECT_FALSE(mFeedback->isPaused());
EXPECT_CALL(*mImpl, pause());
mFeedback->pause();
......@@ -95,7 +95,7 @@ TEST_F(TransformFeedbackTest, SideEffectsOfPauseAndResume)
mFeedback->resume();
EXPECT_FALSE(mFeedback->isPaused());
EXPECT_CALL(*mImpl, end());
mFeedback->end();
mFeedback->end(nullptr);
}
TEST_F(TransformFeedbackTest, BufferBinding)
......
......@@ -29,6 +29,7 @@ class BufferImpl : angle::NonCopyable
public:
BufferImpl(const gl::BufferState &state) : mState(state) {}
virtual ~BufferImpl() { }
virtual void destroy(ContextImpl *contextImpl) {}
virtual gl::Error setData(ContextImpl *context,
GLenum target,
......
......@@ -24,12 +24,15 @@ struct Rectangle;
namespace rx
{
class DisplayImpl;
class FramebufferImpl : angle::NonCopyable
{
public:
explicit FramebufferImpl(const gl::FramebufferState &state) : mState(state) {}
virtual ~FramebufferImpl() { }
virtual void destroy(ContextImpl *contextImpl) {}
virtual void destroyDefault(DisplayImpl *displayImpl) {}
virtual gl::Error discard(size_t count, const GLenum *attachments) = 0;
virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0;
......
......@@ -21,7 +21,7 @@ class MockFramebufferImpl : public rx::FramebufferImpl
{
public:
MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState()) {}
virtual ~MockFramebufferImpl() { destroy(); }
virtual ~MockFramebufferImpl() { destructor(); }
MOCK_METHOD2(discard, gl::Error(size_t, const GLenum *));
MOCK_METHOD2(invalidate, gl::Error(size_t, const GLenum *));
......@@ -48,7 +48,7 @@ class MockFramebufferImpl : public rx::FramebufferImpl
MOCK_METHOD1(syncState, void(const gl::Framebuffer::DirtyBits &));
MOCK_METHOD0(destroy, void());
MOCK_METHOD0(destructor, void());
};
inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock()
......@@ -59,7 +59,7 @@ inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock()
ON_CALL(*framebufferImpl, checkStatus()).WillByDefault(::testing::Return(true));
// We must mock the destructor since NiceMock doesn't work for destructors.
EXPECT_CALL(*framebufferImpl, destroy()).Times(1).RetiresOnSaturation();
EXPECT_CALL(*framebufferImpl, destructor()).Times(1).RetiresOnSaturation();
return framebufferImpl;
}
......
......@@ -33,13 +33,12 @@ class ContextImpl;
using LinkResult = gl::ErrorOrResult<bool>;
class ContextImpl;
class ProgramImpl : angle::NonCopyable
{
public:
ProgramImpl(const gl::ProgramState &state) : mState(state) {}
virtual ~ProgramImpl() {}
virtual void destroy(const ContextImpl *contextImpl) {}
virtual LinkResult load(const ContextImpl *contextImpl,
gl::InfoLog &infoLog,
......
......@@ -21,7 +21,7 @@ class MockProgramImpl : public rx::ProgramImpl
{
public:
MockProgramImpl() : ProgramImpl(gl::ProgramState()) {}
virtual ~MockProgramImpl() { destroy(); }
virtual ~MockProgramImpl() { destructor(); }
MOCK_METHOD3(load, LinkResult(const ContextImpl *, gl::InfoLog &, gl::BinaryInputStream *));
MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
......@@ -59,7 +59,7 @@ class MockProgramImpl : public rx::ProgramImpl
MOCK_METHOD4(setPathFragmentInputGen,
void(const std::string &, GLenum, GLint, const GLfloat *));
MOCK_METHOD0(destroy, void());
MOCK_METHOD0(destructor, void());
};
inline ::testing::NiceMock<MockProgramImpl> *MakeProgramMock()
......@@ -67,7 +67,7 @@ inline ::testing::NiceMock<MockProgramImpl> *MakeProgramMock()
::testing::NiceMock<MockProgramImpl> *programImpl = new ::testing::NiceMock<MockProgramImpl>();
// TODO(jmadill): add ON_CALLS for returning methods
// We must mock the destructor since NiceMock doesn't work for destructors.
EXPECT_CALL(*programImpl, destroy()).Times(1).RetiresOnSaturation();
EXPECT_CALL(*programImpl, destructor()).Times(1).RetiresOnSaturation();
return programImpl;
}
......
......@@ -97,7 +97,7 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError)
state.setVertexArrayBinding(vertexArray);
state.setDrawFramebufferBinding(framebuffer);
state.setProgram(program);
state.setProgram(nullptr, program);
NiceMock<MockValidationContext> testContext(nullptr, nullptr, Version(3, 0), &state, caps,
textureCaps, extensions, limitations, false);
......@@ -119,7 +119,7 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError)
state.setVertexArrayBinding(nullptr);
state.setDrawFramebufferBinding(nullptr);
state.setProgram(nullptr);
state.setProgram(nullptr, nullptr);
SafeDelete(vertexArray);
SafeDelete(framebuffer);
......
......@@ -715,7 +715,7 @@ void GL_APIENTRY DetachShader(GLuint program, GLuint shader)
return;
}
if (!programObject->detachShader(shaderObject))
if (!programObject->detachShader(context, shaderObject))
{
context->handleError(Error(GL_INVALID_OPERATION));
return;
......
......@@ -692,7 +692,7 @@ void GL_APIENTRY EndTransformFeedback(void)
return;
}
transformFeedback->end();
transformFeedback->end(context);
}
}
......
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