summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-01 22:41:16 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-01 22:41:16 +0000
commitd304cbdeccf3db7330c09cb218096a45a2bdc746 (patch)
treed0b939398f1fe3f4beb1def5fbede824d1dea94d
parente7f7509f4ab3672f61e6fc5ec6b5ce0b5eefb4a8 (diff)
downloadchromium_src-d304cbdeccf3db7330c09cb218096a45a2bdc746.zip
chromium_src-d304cbdeccf3db7330c09cb218096a45a2bdc746.tar.gz
chromium_src-d304cbdeccf3db7330c09cb218096a45a2bdc746.tar.bz2
Free the resources used by a context group.
TEST=unit tests BUG=none Review URL: http://codereview.chromium.org/2880013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51441 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--gpu/command_buffer/service/buffer_manager.cc18
-rw-r--r--gpu/command_buffer/service/buffer_manager.h4
-rw-r--r--gpu/command_buffer/service/buffer_manager_unittest.cc28
-rw-r--r--gpu/command_buffer/service/context_group.cc39
-rw-r--r--gpu/command_buffer/service/context_group.h3
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.cc18
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.h4
-rw-r--r--gpu/command_buffer/service/framebuffer_manager_unittest.cc28
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc1
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc4
-rw-r--r--gpu/command_buffer/service/gpu_processor.h2
-rw-r--r--gpu/command_buffer/service/gpu_processor_unittest.cc5
-rw-r--r--gpu/command_buffer/service/program_manager.cc17
-rw-r--r--gpu/command_buffer/service/program_manager.h4
-rw-r--r--gpu/command_buffer/service/program_manager_unittest.cc32
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager.cc18
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager.h4
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager_unittest.cc27
-rw-r--r--gpu/command_buffer/service/shader_manager.cc17
-rw-r--r--gpu/command_buffer/service/shader_manager.h7
-rw-r--r--gpu/command_buffer/service/shader_manager_unittest.cc30
-rw-r--r--gpu/command_buffer/service/texture_manager.cc18
-rw-r--r--gpu/command_buffer/service/texture_manager.h4
-rw-r--r--gpu/command_buffer/service/texture_manager_unittest.cc41
24 files changed, 371 insertions, 2 deletions
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index c4c750e..2abc764 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -10,6 +10,24 @@
namespace gpu {
namespace gles2 {
+BufferManager::~BufferManager() {
+ DCHECK(buffer_infos_.empty());
+}
+
+void BufferManager::Destroy(bool have_context) {
+ while (!buffer_infos_.empty()) {
+ if (have_context) {
+ BufferInfo* info = buffer_infos_.begin()->second;
+ if (!info->IsDeleted()) {
+ GLuint service_id = info->service_id();
+ glDeleteBuffersARB(1, &service_id);
+ info->MarkAsDeleted();
+ }
+ }
+ buffer_infos_.erase(buffer_infos_.begin());
+ }
+}
+
void BufferManager::CreateBufferInfo(GLuint client_id, GLuint service_id) {
std::pair<BufferInfoMap::iterator, bool> result =
buffer_infos_.insert(
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index bc0d1db..f89faeb 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -143,6 +143,10 @@ class BufferManager {
BufferManager()
: allow_buffers_on_multiple_targets_(false) {
}
+ ~BufferManager();
+
+ // Must call before destruction.
+ void Destroy(bool have_context);
// Creates a BufferInfo for the given buffer.
void CreateBufferInfo(GLuint client_id, GLuint service_id);
diff --git a/gpu/command_buffer/service/buffer_manager_unittest.cc b/gpu/command_buffer/service/buffer_manager_unittest.cc
index 96a4f03..3f78fbe 100644
--- a/gpu/command_buffer/service/buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/buffer_manager_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "gpu/command_buffer/service/buffer_manager.h"
+#include "app/gfx/gl/gl_mock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gpu {
@@ -12,18 +13,27 @@ class BufferManagerTest : public testing::Test {
public:
BufferManagerTest() {
}
+ ~BufferManagerTest() {
+ manager_.Destroy(false);
+ }
protected:
virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
}
virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
}
GLenum GetTarget(const BufferManager::BufferInfo* info) const {
return info->target();
}
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
BufferManager manager_;
};
@@ -58,6 +68,24 @@ TEST_F(BufferManagerTest, Basic) {
EXPECT_TRUE(manager_.GetBufferInfo(kClientBuffer1Id) == NULL);
}
+TEST_F(BufferManagerTest, Destroy) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ // Check we can create buffer.
+ manager_.CreateBufferInfo(kClient1Id, kService1Id);
+ // Check buffer got created.
+ BufferManager::BufferInfo* info1 =
+ manager_.GetBufferInfo(kClient1Id);
+ ASSERT_TRUE(info1 != NULL);
+ EXPECT_CALL(*gl_, DeleteBuffersARB(1, ::testing::Pointee(kService1Id)))
+ .Times(1)
+ .RetiresOnSaturation();
+ manager_.Destroy(true);
+ // Check the resources were released.
+ info1 = manager_.GetBufferInfo(kClient1Id);
+ ASSERT_TRUE(info1 == NULL);
+}
+
TEST_F(BufferManagerTest, SetRange) {
const GLuint kClientBufferId = 1;
const GLuint kServiceBufferId = 11;
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 71b796c..4f30ad5 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -26,6 +26,13 @@ ContextGroup::ContextGroup()
}
ContextGroup::~ContextGroup() {
+ // Check that Destroy has been called.
+ DCHECK(buffer_manager_ == NULL);
+ DCHECK(framebuffer_manager_ == NULL);
+ DCHECK(renderbuffer_manager_ == NULL);
+ DCHECK(texture_manager_ == NULL);
+ DCHECK(program_manager_ == NULL);
+ DCHECK(shader_manager_ == NULL);
}
static void GetIntegerv(GLenum pname, uint32* var) {
@@ -87,6 +94,38 @@ bool ContextGroup::Initialize() {
return true;
}
+void ContextGroup::Destroy(bool have_context) {
+ if (buffer_manager_ != NULL) {
+ buffer_manager_->Destroy(have_context);
+ buffer_manager_.reset();
+ }
+
+ if (framebuffer_manager_ != NULL) {
+ framebuffer_manager_->Destroy(have_context);
+ framebuffer_manager_.reset();
+ }
+
+ if (renderbuffer_manager_ != NULL) {
+ renderbuffer_manager_->Destroy(have_context);
+ renderbuffer_manager_.reset();
+ }
+
+ if (texture_manager_ != NULL) {
+ texture_manager_->Destroy(have_context);
+ texture_manager_.reset();
+ }
+
+ if (program_manager_ != NULL) {
+ program_manager_->Destroy(have_context);
+ program_manager_.reset();
+ }
+
+ if (shader_manager_ != NULL) {
+ shader_manager_->Destroy(have_context);
+ shader_manager_.reset();
+ }
+}
+
IdAllocator* ContextGroup::GetIdAllocator(unsigned namespace_id) {
IdAllocatorMap::iterator it = id_namespaces_.find(namespace_id);
if (it != id_namespaces_.end()) {
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h
index 477983f..21fc061 100644
--- a/gpu/command_buffer/service/context_group.h
+++ b/gpu/command_buffer/service/context_group.h
@@ -35,6 +35,9 @@ class ContextGroup {
// This should only be called by GLES2Decoder.
bool Initialize();
+ // Destroys all the resources. MUST be called before destruction.
+ void Destroy(bool have_context);
+
uint32 max_vertex_attribs() const {
return max_vertex_attribs_;
}
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index 1a7d739..8dd036b 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -9,6 +9,24 @@
namespace gpu {
namespace gles2 {
+FramebufferManager::~FramebufferManager() {
+ DCHECK(framebuffer_infos_.empty());
+}
+
+void FramebufferManager::Destroy(bool have_context) {
+ while (!framebuffer_infos_.empty()) {
+ if (have_context) {
+ FramebufferInfo* info = framebuffer_infos_.begin()->second;
+ if (!info->IsDeleted()) {
+ GLuint service_id = info->service_id();
+ glDeleteFramebuffersEXT(1, &service_id);
+ info->MarkAsDeleted();
+ }
+ }
+ framebuffer_infos_.erase(framebuffer_infos_.begin());
+ }
+}
+
void FramebufferManager::CreateFramebufferInfo(
GLuint client_id, GLuint service_id) {
std::pair<FramebufferInfoMap::iterator, bool> result =
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index 3ecb54b..f437e6a 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -63,6 +63,10 @@ class FramebufferManager {
};
FramebufferManager() { }
+ ~FramebufferManager();
+
+ // Must call before destruction.
+ void Destroy(bool have_context);
// Creates a FramebufferInfo for the given framebuffer.
void CreateFramebufferInfo(GLuint client_id, GLuint service_id);
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index 75d0da6..ed435c1 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "gpu/command_buffer/service/framebuffer_manager.h"
+#include "app/gfx/gl/gl_mock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gpu {
@@ -12,14 +13,23 @@ class FramebufferManagerTest : public testing::Test {
public:
FramebufferManagerTest() {
}
+ ~FramebufferManagerTest() {
+ manager_.Destroy(false);
+ }
protected:
virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
}
virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
}
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
FramebufferManager manager_;
};
@@ -47,6 +57,24 @@ TEST_F(FramebufferManagerTest, Basic) {
EXPECT_TRUE(manager_.GetFramebufferInfo(kClient1Id) == NULL);
}
+TEST_F(FramebufferManagerTest, Destroy) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ // Check we can create framebuffer.
+ manager_.CreateFramebufferInfo(kClient1Id, kService1Id);
+ // Check framebuffer got created.
+ FramebufferManager::FramebufferInfo* info1 =
+ manager_.GetFramebufferInfo(kClient1Id);
+ ASSERT_TRUE(info1 != NULL);
+ EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, ::testing::Pointee(kService1Id)))
+ .Times(1)
+ .RetiresOnSaturation();
+ manager_.Destroy(true);
+ // Check the resources were released.
+ info1 = manager_.GetFramebufferInfo(kClient1Id);
+ ASSERT_TRUE(info1 == NULL);
+}
+
// TODO(gman): Write test for AttachRenderbuffer
} // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 2671058..edb5745 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -201,6 +201,7 @@ void GLES2DecoderTestBase::TearDown() {
.RetiresOnSaturation();
decoder_->Destroy();
decoder_.reset();
+ group_.Destroy(false);
engine_.reset();
::gfx::GLInterface::SetGLInterface(NULL);
gl_.reset();
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
index 993e81e..7872b22 100644
--- a/gpu/command_buffer/service/gpu_processor.cc
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -70,11 +70,15 @@ bool GPUProcessor::InitializeCommon(const gfx::Size& size,
}
void GPUProcessor::DestroyCommon() {
+ bool have_context = false;
if (decoder_.get()) {
+ have_context = decoder_->MakeCurrent();
decoder_->Destroy();
decoder_.reset();
}
+ group_.Destroy(have_context);
+
if (context_.get()) {
context_->Destroy();
context_.reset();
diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h
index 7d5a110..f1b2a5d 100644
--- a/gpu/command_buffer/service/gpu_processor.h
+++ b/gpu/command_buffer/service/gpu_processor.h
@@ -98,6 +98,8 @@ class GPUProcessor : public CommandBufferEngine {
int commands_per_update_;
+ // TODO(gman): Group needs to be passed in so it can be shared by
+ // multiple GPUProcessors.
gles2::ContextGroup group_;
scoped_ptr<gles2::GLES2Decoder> decoder_;
scoped_ptr<CommandParser> parser_;
diff --git a/gpu/command_buffer/service/gpu_processor_unittest.cc b/gpu/command_buffer/service/gpu_processor_unittest.cc
index a91cc4c..da2b9e0 100644
--- a/gpu/command_buffer/service/gpu_processor_unittest.cc
+++ b/gpu/command_buffer/service/gpu_processor_unittest.cc
@@ -61,6 +61,10 @@ class GPUProcessorTest : public testing::Test {
decoder_,
parser_,
2));
+
+ EXPECT_CALL(*decoder_, Destroy())
+ .Times(1)
+ .RetiresOnSaturation();
}
virtual void TearDown() {
@@ -148,6 +152,7 @@ TEST_F(GPUProcessorTest, ProcessesTwoCommands) {
TEST_F(GPUProcessorTest, ProcessorSetsTheGLContext) {
EXPECT_CALL(*decoder_, MakeCurrent())
+ .WillOnce(Return(true))
.WillOnce(Return(true));
CommandBuffer::State state;
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index 66605b3..55d1268 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -307,6 +307,23 @@ bool ProgramManager::ProgramInfo::CanLink() const {
return true;
}
+ProgramManager::~ProgramManager() {
+ DCHECK(program_infos_.empty());
+}
+
+void ProgramManager::Destroy(bool have_context) {
+ while (!program_infos_.empty()) {
+ if (have_context) {
+ ProgramInfo* info = program_infos_.begin()->second;
+ if (!info->IsDeleted()) {
+ glDeleteProgram(info->service_id());
+ info->MarkAsDeleted();
+ }
+ }
+ program_infos_.erase(program_infos_.begin());
+ }
+}
+
void ProgramManager::CreateProgramInfo(GLuint client_id, GLuint service_id) {
std::pair<ProgramInfoMap::iterator, bool> result =
program_infos_.insert(
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 995caa2..66c09f2 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -197,6 +197,10 @@ class ProgramManager {
};
ProgramManager() { }
+ ~ProgramManager();
+
+ // Must call before destruction.
+ void Destroy(bool have_context);
// Creates a new program info.
void CreateProgramInfo(GLuint client_id, GLuint service_id);
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc
index a3a47d9..3faf14e 100644
--- a/gpu/command_buffer/service/program_manager_unittest.cc
+++ b/gpu/command_buffer/service/program_manager_unittest.cc
@@ -26,14 +26,23 @@ namespace gles2 {
class ProgramManagerTest : public testing::Test {
public:
ProgramManagerTest() { }
+ ~ProgramManagerTest() {
+ manager_.Destroy(false);
+ }
protected:
virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
}
virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
}
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
ProgramManager manager_;
};
@@ -61,12 +70,34 @@ TEST_F(ProgramManagerTest, Basic) {
EXPECT_TRUE(manager_.GetProgramInfo(kClient1Id) == NULL);
}
+TEST_F(ProgramManagerTest, Destroy) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ // Check we can create program.
+ manager_.CreateProgramInfo(kClient1Id, kService1Id);
+ // Check program got created.
+ ProgramManager::ProgramInfo* info1 =
+ manager_.GetProgramInfo(kClient1Id);
+ ASSERT_TRUE(info1 != NULL);
+ EXPECT_CALL(*gl_, DeleteProgram(kService1Id))
+ .Times(1)
+ .RetiresOnSaturation();
+ manager_.Destroy(true);
+ // Check the resources were released.
+ info1 = manager_.GetProgramInfo(kClient1Id);
+ ASSERT_TRUE(info1 == NULL);
+}
+
class ProgramManagerWithShaderTest : public testing::Test {
public:
ProgramManagerWithShaderTest()
: program_info_(NULL) {
}
+ ~ProgramManagerWithShaderTest() {
+ manager_.Destroy(false);
+ }
+
static const GLint kNumVertexAttribs = 16;
static const GLuint kClientProgramId = 123;
@@ -410,6 +441,7 @@ TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) {
EXPECT_FALSE(program_info->CanLink());
fshader->SetStatus(true, "");
EXPECT_TRUE(program_info->CanLink());
+ shader_manager.Destroy(false);
}
TEST_F(ProgramManagerWithShaderTest, GetUniformLocation) {
diff --git a/gpu/command_buffer/service/renderbuffer_manager.cc b/gpu/command_buffer/service/renderbuffer_manager.cc
index 63aee26..88a2d26 100644
--- a/gpu/command_buffer/service/renderbuffer_manager.cc
+++ b/gpu/command_buffer/service/renderbuffer_manager.cc
@@ -10,6 +10,24 @@
namespace gpu {
namespace gles2 {
+RenderbufferManager::~RenderbufferManager() {
+ DCHECK(renderbuffer_infos_.empty());
+}
+
+void RenderbufferManager::Destroy(bool have_context) {
+ while (!renderbuffer_infos_.empty()) {
+ if (have_context) {
+ RenderbufferInfo* info = renderbuffer_infos_.begin()->second;
+ if (!info->IsDeleted()) {
+ GLuint service_id = info->service_id();
+ glDeleteRenderbuffersEXT(1, &service_id);
+ info->MarkAsDeleted();
+ }
+ }
+ renderbuffer_infos_.erase(renderbuffer_infos_.begin());
+ }
+}
+
void RenderbufferManager::CreateRenderbufferInfo(
GLuint client_id, GLuint service_id) {
std::pair<RenderbufferInfoMap::iterator, bool> result =
diff --git a/gpu/command_buffer/service/renderbuffer_manager.h b/gpu/command_buffer/service/renderbuffer_manager.h
index e5f1c0b..50b64a9 100644
--- a/gpu/command_buffer/service/renderbuffer_manager.h
+++ b/gpu/command_buffer/service/renderbuffer_manager.h
@@ -75,6 +75,10 @@ class RenderbufferManager {
};
RenderbufferManager() { }
+ ~RenderbufferManager();
+
+ // Must call before destruction.
+ void Destroy(bool have_context);
// Creates a RenderbufferInfo for the given renderbuffer.
void CreateRenderbufferInfo(GLuint client_id, GLuint service_id);
diff --git a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
index 0cedaea..05c51ce 100644
--- a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "gpu/command_buffer/service/renderbuffer_manager.h"
+#include "app/gfx/gl/gl_mock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gpu {
@@ -12,14 +13,23 @@ class RenderbufferManagerTest : public testing::Test {
public:
RenderbufferManagerTest() {
}
+ ~RenderbufferManagerTest() {
+ manager_.Destroy(false);
+ }
protected:
virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock<gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
}
virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
}
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
RenderbufferManager manager_;
};
@@ -50,6 +60,23 @@ TEST_F(RenderbufferManagerTest, Basic) {
EXPECT_TRUE(manager_.GetRenderbufferInfo(kClient1Id) == NULL);
}
+TEST_F(RenderbufferManagerTest, Destroy) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ // Check we can create renderbuffer.
+ manager_.CreateRenderbufferInfo(kClient1Id, kService1Id);
+ // Check renderbuffer got created.
+ RenderbufferManager::RenderbufferInfo* info1 =
+ manager_.GetRenderbufferInfo(kClient1Id);
+ ASSERT_TRUE(info1 != NULL);
+ EXPECT_CALL(*gl_, DeleteRenderbuffersEXT(1, ::testing::Pointee(kService1Id)))
+ .Times(1)
+ .RetiresOnSaturation();
+ manager_.Destroy(true);
+ info1 = manager_.GetRenderbufferInfo(kClient1Id);
+ ASSERT_TRUE(info1 == NULL);
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc
index 36a7b1a..eb4a899 100644
--- a/gpu/command_buffer/service/shader_manager.cc
+++ b/gpu/command_buffer/service/shader_manager.cc
@@ -8,6 +8,23 @@
namespace gpu {
namespace gles2 {
+ShaderManager::~ShaderManager() {
+ DCHECK(shader_infos_.empty());
+}
+
+void ShaderManager::Destroy(bool have_context) {
+ while (!shader_infos_.empty()) {
+ if (have_context) {
+ ShaderInfo* info = shader_infos_.begin()->second;
+ if (!info->IsDeleted()) {
+ glDeleteShader(info->service_id());
+ info->MarkAsDeleted();
+ }
+ }
+ shader_infos_.erase(shader_infos_.begin());
+ }
+}
+
void ShaderManager::CreateShaderInfo(GLuint client_id,
GLuint service_id,
GLenum shader_type) {
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h
index b0bcfa2..d9b8c46 100644
--- a/gpu/command_buffer/service/shader_manager.h
+++ b/gpu/command_buffer/service/shader_manager.h
@@ -91,8 +91,11 @@ class ShaderManager {
std::string log_info_;
};
- ShaderManager() {
- }
+ ShaderManager() { }
+ ~ShaderManager();
+
+ // Must call before destruction.
+ void Destroy(bool have_context);
// Creates a shader info for the given shader ID.
void CreateShaderInfo(GLuint client_id,
diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc
index e93a65ef..ccccb22 100644
--- a/gpu/command_buffer/service/shader_manager_unittest.cc
+++ b/gpu/command_buffer/service/shader_manager_unittest.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "gpu/command_buffer/service/shader_manager.h"
+#include "base/scoped_ptr.h"
+#include "app/gfx/gl/gl_mock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gpu {
@@ -13,13 +15,23 @@ class ShaderManagerTest : public testing::Test {
ShaderManagerTest() {
}
+ ~ShaderManagerTest() {
+ manager_.Destroy(false);
+ }
+
protected:
virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
}
virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
}
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
ShaderManager manager_;
};
@@ -55,6 +67,24 @@ TEST_F(ShaderManagerTest, Basic) {
EXPECT_TRUE(manager_.GetShaderInfo(kClient1Id) == NULL);
}
+TEST_F(ShaderManagerTest, Destroy) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ const GLenum kShader1Type = GL_VERTEX_SHADER;
+ // Check we can create shader.
+ manager_.CreateShaderInfo(kClient1Id, kService1Id, kShader1Type);
+ // Check shader got created.
+ ShaderManager::ShaderInfo* info1 = manager_.GetShaderInfo(kClient1Id);
+ ASSERT_TRUE(info1 != NULL);
+ EXPECT_CALL(*gl_, DeleteShader(kService1Id))
+ .Times(1)
+ .RetiresOnSaturation();
+ manager_.Destroy(true);
+ // Check that resources got freed.
+ info1 = manager_.GetShaderInfo(kClient1Id);
+ ASSERT_TRUE(info1 == NULL);
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 73c3480..da4b8a561 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -58,6 +58,24 @@ static size_t FaceIndexToGLTarget(size_t index) {
}
}
+TextureManager::~TextureManager() {
+ DCHECK(texture_infos_.empty());
+}
+
+void TextureManager::Destroy(bool have_context) {
+ while (!texture_infos_.empty()) {
+ if (have_context) {
+ TextureInfo* info = texture_infos_.begin()->second;
+ if (!info->IsDeleted()) {
+ GLuint service_id = info->service_id();
+ glDeleteTextures(1, &service_id);
+ info->MarkAsDeleted();
+ }
+ }
+ texture_infos_.erase(texture_infos_.begin());
+ }
+}
+
bool TextureManager::TextureInfo::CanRender() const {
if (target_ == 0 || IsDeleted()) {
return false;
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index a2d70dd..1df58c4 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -195,6 +195,10 @@ class TextureManager {
TextureManager(GLsizei max_texture_size,
GLsizei max_cube_map_texture_size);
+ ~TextureManager();
+
+ // Must call before destruction.
+ void Destroy(bool have_context);
// Returns the maximum number of levels.
GLint MaxLevelsForTarget(GLenum target) const {
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc
index 97cfd02..417454b 100644
--- a/gpu/command_buffer/service/texture_manager_unittest.cc
+++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -3,8 +3,12 @@
// found in the LICENSE file.
#include "gpu/command_buffer/service/texture_manager.h"
+#include "base/scoped_ptr.h"
+#include "app/gfx/gl/gl_mock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::Pointee;
+
namespace gpu {
namespace gles2 {
@@ -19,13 +23,23 @@ class TextureManagerTest : public testing::Test {
: manager_(kMaxTextureSize, kMaxCubeMapTextureSize) {
}
+ ~TextureManagerTest() {
+ manager_.Destroy(false);
+ }
+
protected:
virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
}
virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
}
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
TextureManager manager_;
};
@@ -60,6 +74,24 @@ TEST_F(TextureManagerTest, Basic) {
EXPECT_TRUE(manager_.GetTextureInfo(kClient1Id) == NULL);
}
+TEST_F(TextureManagerTest, Destroy) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ EXPECT_FALSE(manager_.HaveUnrenderableTextures());
+ // Check we can create texture.
+ manager_.CreateTextureInfo(kClient1Id, kService1Id);
+ // Check texture got created.
+ TextureManager::TextureInfo* info1 = manager_.GetTextureInfo(kClient1Id);
+ ASSERT_TRUE(info1 != NULL);
+ EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService1Id)))
+ .Times(1)
+ .RetiresOnSaturation();
+ manager_.Destroy(true);
+ // Check that resources got freed.
+ info1 = manager_.GetTextureInfo(kClient1Id);
+ ASSERT_TRUE(info1 == NULL);
+}
+
TEST_F(TextureManagerTest, MaxValues) {
// Check we get the right values for the max sizes.
EXPECT_EQ(kMax2dLevels, manager_.MaxLevelsForTarget(GL_TEXTURE_2D));
@@ -126,17 +158,26 @@ class TextureInfoTest : public testing::Test {
TextureInfoTest()
: manager_(kMaxTextureSize, kMaxCubeMapTextureSize) {
}
+ ~TextureInfoTest() {
+ manager_.Destroy(false);
+ }
protected:
virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
manager_.CreateTextureInfo(kClient1Id, kService1Id);
info_ = manager_.GetTextureInfo(kClient1Id);
ASSERT_TRUE(info_ != NULL);
}
virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
}
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
TextureManager manager_;
TextureManager::TextureInfo* info_;
};