Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Unified Diff: gpu/command_buffer/client/share_group.cc

Issue 9918027: Make ShareGroup thread safe (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add id==0 check Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/client/share_group.h ('k') | gpu/command_buffer/client/share_group_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/command_buffer/client/share_group.cc
diff --git a/gpu/command_buffer/client/share_group.cc b/gpu/command_buffer/client/share_group.cc
index 3e3b7e601eb49408ea0733e778bafea6e8e8487e..98b13c52d338fddec134582501452fdb7a6222c1 100644
--- a/gpu/command_buffer/client/share_group.cc
+++ b/gpu/command_buffer/client/share_group.cc
@@ -2,19 +2,320 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "../client/atomicops.h"
#include "../client/share_group.h"
+#include "../client/gles2_implementation.h"
+#include "../client/program_info_manager.h"
+#include "../common/id_allocator.h"
#include "../common/logging.h"
namespace gpu {
namespace gles2 {
-ShareGroup::ShareGroup() {
+COMPILE_ASSERT(gpu::kInvalidResource == 0,
+ INVALID_RESOURCE_NOT_0_AS_GL_EXPECTS);
+
+// An id handler for non-shared ids.
+class NonSharedIdHandler : public IdHandlerInterface {
+ public:
+ NonSharedIdHandler() { }
+ virtual ~NonSharedIdHandler() { }
+
+ // Overridden from IdHandlerInterface.
+ virtual void Destroy(GLES2Implementation* /* gl_impl */) {
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual void MakeIds(
+ GLES2Implementation* /* gl_impl */,
+ GLuint id_offset, GLsizei n, GLuint* ids) {
+ if (id_offset == 0) {
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ ids[ii] = id_allocator_.AllocateID();
+ }
+ } else {
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ ids[ii] = id_allocator_.AllocateIDAtOrAbove(id_offset);
+ id_offset = ids[ii] + 1;
+ }
+ }
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual bool FreeIds(
+ GLES2Implementation* /* gl_impl */,
+ GLsizei n, const GLuint* ids) {
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ id_allocator_.FreeID(ids[ii]);
+ }
+ return true;
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual bool MarkAsUsedForBind(GLuint id) {
+ return id == 0 ? true : id_allocator_.MarkAsUsed(id);
+ }
+ private:
+ IdAllocator id_allocator_;
+};
+
+// An id handler for non-shared ids that are never reused.
+class NonSharedNonReusedIdHandler : public IdHandlerInterface {
+ public:
+ NonSharedNonReusedIdHandler() : last_id_(0) { }
+ virtual ~NonSharedNonReusedIdHandler() { }
+
+ // Overridden from IdHandlerInterface.
+ virtual void Destroy(GLES2Implementation* /* gl_impl */) {
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual void MakeIds(
+ GLES2Implementation* /* gl_impl */,
+ GLuint id_offset, GLsizei n, GLuint* ids) {
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ ids[ii] = ++last_id_ + id_offset;
+ }
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual bool FreeIds(
+ GLES2Implementation* /* gl_impl */,
+ GLsizei /* n */, const GLuint* /* ids */) {
+ // Ids are never freed.
+ return true;
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual bool MarkAsUsedForBind(GLuint /* id */) {
+ // This is only used for Shaders and Programs which have no bind.
+ return false;
+ }
+
+ private:
+ GLuint last_id_;
+};
+
+// An id handler for shared ids.
+class SharedIdHandler : public IdHandlerInterface {
+ public:
+ SharedIdHandler(
+ id_namespaces::IdNamespaces id_namespace)
+ : id_namespace_(id_namespace) {
+ }
+
+ virtual ~SharedIdHandler() { }
+
+ // Overridden from IdHandlerInterface.
+ virtual void Destroy(GLES2Implementation* /* gl_impl */) {
+ }
+
+ virtual void MakeIds(
+ GLES2Implementation* gl_impl,
+ GLuint id_offset, GLsizei n, GLuint* ids) {
+ gl_impl->GenSharedIdsCHROMIUM(id_namespace_, id_offset, n, ids);
+ }
+
+ virtual bool FreeIds(
+ GLES2Implementation* gl_impl,
+ GLsizei n, const GLuint* ids) {
+ gl_impl->DeleteSharedIdsCHROMIUM(id_namespace_, n, ids);
+ // We need to ensure that the delete call is evaluated on the service side
+ // before any other contexts issue commands using these client ids.
+ gl_impl->helper()->CommandBufferHelper::Flush();
+ return true;
+ }
+
+ virtual bool MarkAsUsedForBind(GLuint /* id */) {
+ // This has no meaning for shared resources.
+ return true;
+ }
+
+ private:
+ id_namespaces::IdNamespaces id_namespace_;
+};
+
+// An id handler for shared ids that requires ids are made before using and
+// that only the context that created the id can delete it.
+// Assumes the service will enforce that non made ids generate an error.
+class StrictSharedIdHandler : public IdHandlerInterface {
+ public:
+ StrictSharedIdHandler(
+ id_namespaces::IdNamespaces id_namespace)
+ : id_namespace_(id_namespace) {
+ }
+
+ virtual ~StrictSharedIdHandler() {
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual void Destroy(GLES2Implementation* gl_impl) {
+ GPU_DCHECK(gl_impl);
+ // Free all the ids not being used.
+ while (!free_ids_.empty()) {
+ GLuint ids[kNumIdsToGet];
+ int count = 0;
+ while (count < kNumIdsToGet && !free_ids_.empty()) {
+ ids[count++] = free_ids_.front();
+ free_ids_.pop();
+ }
+ gl_impl->DeleteSharedIdsCHROMIUM(id_namespace_, count, ids);
+ }
+ }
+
+ virtual void MakeIds(
+ GLES2Implementation* gl_impl,
+ GLuint id_offset, GLsizei n, GLuint* ids) {
+ GPU_DCHECK(gl_impl);
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ ids[ii] = GetId(gl_impl, id_offset);
+ }
+ }
+
+ virtual bool FreeIds(
+ GLES2Implementation* /* gl_impl */,
+ GLsizei n, const GLuint* ids) {
+ // OpenGL sematics. If any id is bad none of them get freed.
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ GLuint id = ids[ii];
+ if (id != 0) {
+ ResourceIdSet::iterator it = used_ids_.find(id);
+ if (it == used_ids_.end()) {
+ return false;
+ }
+ }
+ }
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ GLuint id = ids[ii];
+ if (id != 0) {
+ ResourceIdSet::iterator it = used_ids_.find(id);
+ if (it != used_ids_.end()) {
+ used_ids_.erase(it);
+ free_ids_.push(id);
+ }
+ }
+ }
+ return true;
+ }
+
+ virtual bool MarkAsUsedForBind(GLuint id) {
+ GPU_DCHECK(id == 0 || used_ids_.find(id) != used_ids_.end());
+ // This has no meaning for shared resources.
+ return true;
+ }
+
+ private:
+ static const GLsizei kNumIdsToGet = 2048;
+ typedef std::queue<GLuint> ResourceIdQueue;
+ typedef std::set<GLuint> ResourceIdSet;
+
+ GLuint GetId(GLES2Implementation* gl_impl, GLuint id_offset) {
+ GPU_DCHECK(gl_impl);
+ if (free_ids_.empty()) {
+ GLuint ids[kNumIdsToGet];
+ gl_impl->GenSharedIdsCHROMIUM(
+ id_namespace_, id_offset, kNumIdsToGet, ids);
+ for (GLsizei ii = 0; ii < kNumIdsToGet; ++ii) {
+ free_ids_.push(ids[ii]);
+ }
+ }
+ GLuint id = free_ids_.front();
+ free_ids_.pop();
+ used_ids_.insert(id);
+ return id;
+ }
+
+ id_namespaces::IdNamespaces id_namespace_;
+ ResourceIdSet used_ids_;
+ ResourceIdQueue free_ids_;
+};
+
+#ifndef _MSC_VER
+const GLsizei StrictSharedIdHandler::kNumIdsToGet;
+#endif
+
+class ThreadSafeIdHandlerWrapper : public IdHandlerInterface {
+ public:
+ ThreadSafeIdHandlerWrapper(IdHandlerInterface* id_handler)
+ : id_handler_(id_handler) {
+ }
+ virtual ~ThreadSafeIdHandlerWrapper() { }
+
+ // Overridden from IdHandlerInterface.
+ virtual void Destroy(GLES2Implementation* gl_impl) {
+ AutoLock auto_lock(lock_);
+ id_handler_->Destroy(gl_impl);
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual void MakeIds(
+ GLES2Implementation* gl_impl, GLuint id_offset, GLsizei n, GLuint* ids) {
+ AutoLock auto_lock(lock_);
+ id_handler_->MakeIds(gl_impl, id_offset, n, ids);
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual bool FreeIds(
+ GLES2Implementation* gl_impl, GLsizei n, const GLuint* ids) {
+ AutoLock auto_lock(lock_);
+ return id_handler_->FreeIds(gl_impl, n, ids);
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual bool MarkAsUsedForBind(GLuint id) {
+ AutoLock auto_lock(lock_);
+ return id_handler_->MarkAsUsedForBind(id);
+ }
+
+ private:
+ IdHandlerInterface* id_handler_;
+ Lock lock_;
+};
+
+ShareGroup::ShareGroup(bool share_resources, bool bind_generates_resource)
+ : sharing_resources_(share_resources),
+ bind_generates_resource_(bind_generates_resource),
+ gles2_(NULL) {
GPU_CHECK(ShareGroup::ImplementsThreadSafeReferenceCounting());
+
+ if (sharing_resources_) {
+ if (!bind_generates_resource_) {
+ for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
+ id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
+ new StrictSharedIdHandler(
+ static_cast<id_namespaces::IdNamespaces>(i))));
+ }
+ } else {
+ for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
+ id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
+ new SharedIdHandler(
+ static_cast<id_namespaces::IdNamespaces>(i))));
+ }
+ }
+ } else {
+ for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
+ if (i == id_namespaces::kProgramsAndShaders)
+ id_handlers_[i].reset(new NonSharedNonReusedIdHandler);
+ else
+ id_handlers_[i].reset(new NonSharedIdHandler);
+ }
+ }
+ program_info_manager_.reset(ProgramInfoManager::Create(sharing_resources_));
}
ShareGroup::~ShareGroup() {
+ for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
+ id_handlers_[i]->Destroy(gles2_);
+ id_handlers_[i].reset();
+ }
+}
+
+void ShareGroup::SetGLES2ImplementationForDestruction(
+ GLES2Implementation* gl_impl) {
+ gles2_ = gl_impl;
}
+
} // namespace gles2
} // namespace gpu
« no previous file with comments | « gpu/command_buffer/client/share_group.h ('k') | gpu/command_buffer/client/share_group_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698