| 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
|
|
|
|
|