summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-31 03:19:02 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-31 03:19:02 +0000
commitc288ca0597d6259501104da2f804b9359cab86bb (patch)
tree215dab341fceb40f034fd5e51f819adb0fbef28f /gpu
parent8add725ecc32ec57f06aca234f03fb4607aa887f (diff)
downloadchromium_src-c288ca0597d6259501104da2f804b9359cab86bb.zip
chromium_src-c288ca0597d6259501104da2f804b9359cab86bb.tar.gz
chromium_src-c288ca0597d6259501104da2f804b9359cab86bb.tar.bz2
Make ShareGroup thread safe
In another CL I'll refactor the id handlers AND make the places sharing resources correctly set things up. TEST=none BUG=120297 Review URL: http://codereview.chromium.org/9918027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@130034 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py9
-rw-r--r--gpu/command_buffer/client/atomicops.cc77
-rw-r--r--gpu/command_buffer/client/atomicops.h37
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc309
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h40
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h28
-rw-r--r--gpu/command_buffer/client/program_info_manager.cc11
-rw-r--r--gpu/command_buffer/client/share_group.cc303
-rw-r--r--gpu/command_buffer/client/share_group.h57
-rw-r--r--gpu/command_buffer/client/share_group_unittest.cc2
10 files changed, 564 insertions, 309 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 64e3240..c658053 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -2761,8 +2761,8 @@ class GENnHandler(TypeHandler):
for arg in func.GetOriginalArgs():
arg.WriteClientSideValidationCode(file, func)
code = """ GPU_CLIENT_SINGLE_THREAD_CHECK();
- id_handlers_[id_namespaces::k%(resource_types)s]->
- MakeIds(0, %(args)s);
+ GetIdHandler(id_namespaces::k%(resource_types)s)->
+ MakeIds(this, 0, %(args)s);
helper_->%(name)sImmediate(%(args)s);
%(log_code)s
}
@@ -3011,8 +3011,9 @@ TEST_F(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
for arg in func.GetOriginalArgs():
arg.WriteClientSideValidationCode(file, func)
file.Write(" GLuint client_id;\n")
- file.Write(" id_handlers_[id_namespaces::kProgramsAndShaders]->\n")
- file.Write(" MakeIds(0, 1, &client_id);\n")
+ file.Write(
+ " GetIdHandler(id_namespaces::kProgramsAndShaders)->\n")
+ file.Write(" MakeIds(this, 0, 1, &client_id);\n")
file.Write(" helper_->%s(%s);\n" %
(func.name, func.MakeCmdArgString("")))
file.Write(' GPU_CLIENT_LOG("returned " << client_id);\n')
diff --git a/gpu/command_buffer/client/atomicops.cc b/gpu/command_buffer/client/atomicops.cc
index 142ab9c..318c337 100644
--- a/gpu/command_buffer/client/atomicops.cc
+++ b/gpu/command_buffer/client/atomicops.cc
@@ -3,9 +3,13 @@
// found in the LICENSE file.
#include "../client/atomicops.h"
+#include "../common/logging.h"
#if !defined(__native_client__)
#include "base/atomicops.h"
+#include "base/synchronization/lock.h"
+#else
+#include <pthread.h>
#endif
namespace gpu {
@@ -18,5 +22,78 @@ void MemoryBarrier() {
#endif
}
+#if defined(__native_client__)
+
+class LockImpl {
+ public:
+ LockImpl()
+ : acquired_(false) {
+ pthread_mutex_init(&mutex_, NULL);
+ }
+
+ ~LockImpl() {
+ pthread_mutex_destroy(&mutex_);
+ }
+
+ void Acquire() {
+ pthread_mutex_lock(&mutex_);
+ acquired_ = true;
+ }
+
+ void Release() {
+ GPU_DCHECK(acquired_);
+ acquired_ = false;
+ pthread_mutex_unlock(&mutex_);
+ }
+
+ bool Try() {
+ bool acquired = pthread_mutex_trylock(&mutex_) == 0;
+ if (acquired) {
+ acquired_ = true;
+ }
+ return acquired;
+ }
+
+ void AssertAcquired() const {
+ GPU_DCHECK(acquired_);
+ }
+
+ private:
+ bool acquired_;
+ pthread_mutex_t mutex_;
+
+ DISALLOW_COPY_AND_ASSIGN(LockImpl);
+};
+
+#else // !__native_client__
+
+class LockImpl : public base::Lock {
+};
+
+#endif // !__native_client__
+
+Lock::Lock()
+ : lock_(new LockImpl()) {
+}
+
+Lock::~Lock() {
+}
+
+void Lock::Acquire() {
+ lock_->Acquire();
+}
+
+void Lock::Release() {
+ lock_->Release();
+}
+
+bool Lock::Try() {
+ return lock_->Try();
+}
+
+void Lock::AssertAcquired() const {
+ return lock_->AssertAcquired();
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/client/atomicops.h b/gpu/command_buffer/client/atomicops.h
index ffd274c..7fa68bd 100644
--- a/gpu/command_buffer/client/atomicops.h
+++ b/gpu/command_buffer/client/atomicops.h
@@ -5,10 +5,47 @@
#ifndef GPU_COMMAND_BUFFER_CLIENT_ATOMICOPS_H_
#define GPU_COMMAND_BUFFER_CLIENT_ATOMICOPS_H_
+#include "../../gpu_export.h"
+#include "../common/scoped_ptr.h"
+#include "../common/types.h"
+
namespace gpu {
void MemoryBarrier();
+class LockImpl;
+class GPU_EXPORT Lock {
+ public:
+ Lock();
+ ~Lock();
+ void Acquire();
+ void Release();
+ bool Try();
+ void AssertAcquired() const;
+
+ private:
+ scoped_ptr<LockImpl> lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(Lock);
+};
+
+// A helper class that acquires the given Lock while the AutoLock is in scope.
+class GPU_EXPORT AutoLock {
+ public:
+ explicit AutoLock(Lock& lock) : lock_(lock) {
+ lock_.Acquire();
+ }
+
+ ~AutoLock() {
+ lock_.AssertAcquired();
+ lock_.Release();
+ }
+
+ private:
+ Lock& lock_;
+ DISALLOW_COPY_AND_ASSIGN(AutoLock);
+};
+
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_CLIENT_ATOMICOPS_H_
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 06aa79e..cfd4063 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -13,10 +13,8 @@
#include "../client/mapped_memory.h"
#include "../client/program_info_manager.h"
#include "../client/query_tracker.h"
-#include "../client/share_group.h"
#include "../client/transfer_buffer.h"
#include "../common/gles2_cmd_utils.h"
-#include "../common/id_allocator.h"
#include "../common/trace_event.h"
#if defined(__native_client__) && !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
@@ -36,198 +34,6 @@ static GLuint ToGLuint(const void* ptr) {
return static_cast<GLuint>(reinterpret_cast<size_t>(ptr));
}
-// An id handler for non-shared ids.
-class NonSharedIdHandler : public IdHandlerInterface {
- public:
- NonSharedIdHandler() { }
- virtual ~NonSharedIdHandler() { }
-
- // Overridden from IdHandlerInterface.
- virtual void MakeIds(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(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 MakeIds(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(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(
- GLES2Implementation* gles2,
- id_namespaces::IdNamespaces id_namespace)
- : gles2_(gles2),
- id_namespace_(id_namespace) {
- }
-
- virtual ~SharedIdHandler() { }
-
- virtual void MakeIds(GLuint id_offset, GLsizei n, GLuint* ids) {
- gles2_->GenSharedIdsCHROMIUM(id_namespace_, id_offset, n, ids);
- }
-
- virtual bool FreeIds(GLsizei n, const GLuint* ids) {
- gles2_->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.
- gles2_->helper()->CommandBufferHelper::Flush();
- return true;
- }
-
- virtual bool MarkAsUsedForBind(GLuint /* id */) {
- // This has no meaning for shared resources.
- return true;
- }
-
- private:
- GLES2Implementation* gles2_;
- 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(
- GLES2Implementation* gles2,
- id_namespaces::IdNamespaces id_namespace)
- : gles2_(gles2),
- id_namespace_(id_namespace) {
- }
-
- virtual ~StrictSharedIdHandler() {
- Destroy();
- }
-
- virtual void MakeIds(GLuint id_offset, GLsizei n, GLuint* ids) {
- for (GLsizei ii = 0; ii < n; ++ii) {
- ids[ii] = GetId(id_offset);
- }
- }
-
- virtual bool FreeIds(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 */) {
- // 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;
-
- void Destroy() {
- // 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();
- }
- gles2_->DeleteSharedIdsCHROMIUM(id_namespace_, count, ids);
- }
- }
-
- GLuint GetId(GLuint id_offset) {
- if (free_ids_.empty()) {
- GLuint ids[kNumIdsToGet];
- gles2_->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;
- }
-
- GLES2Implementation* gles2_;
- id_namespaces::IdNamespaces id_namespace_;
- ResourceIdSet used_ids_;
- ResourceIdQueue free_ids_;
-};
-
-#ifndef _MSC_VER
-const GLsizei StrictSharedIdHandler::kNumIdsToGet;
-#endif
-
static GLsizei RoundUpToMultipleOf4(GLsizei size) {
return (size + 3) & ~3;
}
@@ -559,9 +365,6 @@ const size_t GLES2Implementation::kMaxSizeOfSimpleResult;
const unsigned int GLES2Implementation::kStartingOffset;
#endif
-COMPILE_ASSERT(gpu::kInvalidResource == 0,
- INVALID_RESOURCE_NOT_0_AS_GL_EXPECTS);
-
GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
GLES2Implementation* gles2_implementation)
: gles2_implementation_(gles2_implementation) {
@@ -596,8 +399,6 @@ GLES2Implementation::GLES2Implementation(
client_side_element_array_id_(0),
error_bits_(0),
debug_(false),
- sharing_resources_(share_resources),
- bind_generates_resource_(bind_generates_resource),
use_count_(0),
current_query_(NULL),
error_message_callback_(NULL) {
@@ -608,7 +409,8 @@ GLES2Implementation::GLES2Implementation(
switches::kEnableGPUClientLogging);
});
- share_group_ = (share_group ? share_group : new ShareGroup());
+ share_group_ = (share_group ? share_group : new ShareGroup(
+ share_resources, bind_generates_resource));
memset(&reserved_ids_, 0, sizeof(reserved_ids_));
}
@@ -634,27 +436,6 @@ bool GLES2Implementation::Initialize(
mapped_memory_.reset(new MappedMemoryManager(helper_));
SetSharedMemoryChunkSizeMultiple(1024 * 1024 * 2);
- if (sharing_resources_) {
- if (!bind_generates_resource_) {
- for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
- id_handlers_[i].reset(new StrictSharedIdHandler(
- this, static_cast<id_namespaces::IdNamespaces>(i)));
- }
- } else {
- for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
- id_handlers_[i].reset(new SharedIdHandler(
- this, 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);
- }
- }
-
static const GLenum pnames[] = {
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
GL_MAX_CUBE_MAP_TEXTURE_SIZE,
@@ -682,12 +463,11 @@ bool GLES2Implementation::Initialize(
texture_units_.reset(
new TextureUnit[gl_state_.max_combined_texture_image_units]);
- program_info_manager_.reset(ProgramInfoManager::Create(sharing_resources_));
query_tracker_.reset(new QueryTracker(mapped_memory_.get()));
#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
- id_handlers_[id_namespaces::kBuffers]->MakeIds(
- kClientSideArrayId, arraysize(reserved_ids_), &reserved_ids_[0]);
+ GetIdHandler(id_namespaces::kBuffers)->MakeIds(
+ this, kClientSideArrayId, arraysize(reserved_ids_), &reserved_ids_[0]);
client_side_buffer_helper_.reset(new ClientSideBufferHelper(
gl_state_.max_vertex_attribs,
@@ -709,13 +489,29 @@ GLES2Implementation::~GLES2Implementation() {
#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]);
#endif
- for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
- id_handlers_[i].reset();
- }
+ // The share group needs to be able to use a command buffer to talk
+ // to service if it's destroyed so set one for it then release the reference.
+ // If it's destroyed it will use this GLES2Implemenation.
+ share_group_->SetGLES2ImplementationForDestruction(this);
+ share_group_ = NULL;
// Make sure the commands make it the service.
Finish();
}
+GLuint GLES2Implementation::MakeTextureId() {
+ GLuint id;
+ GetIdHandler(id_namespaces::kTextures)->MakeIds(this, 0, 1, &id);
+ return id;
+}
+
+void GLES2Implementation::FreeTextureId(GLuint id) {
+ GetIdHandler(id_namespaces::kTextures)->FreeIds(this, 1, &id);
+}
+
+IdHandlerInterface* GLES2Implementation::GetIdHandler(int namespace_id) const {
+ return share_group_->GetIdHandler(namespace_id);
+}
+
void* GLES2Implementation::GetResultBuffer() {
return transfer_buffer_->GetResultBuffer();
}
@@ -961,13 +757,13 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) {
*params = gl_state_.num_shader_binary_formats;
return true;
case GL_ARRAY_BUFFER_BINDING:
- if (bind_generates_resource_) {
+ if (share_group_->bind_generates_resource()) {
*params = bound_array_buffer_id_;
return true;
}
return false;
case GL_ELEMENT_ARRAY_BUFFER_BINDING:
- if (bind_generates_resource_) {
+ if (share_group_->bind_generates_resource()) {
*params = bound_element_array_buffer_id_;
return true;
}
@@ -976,25 +772,25 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) {
*params = active_texture_unit_ + GL_TEXTURE0;
return true;
case GL_TEXTURE_BINDING_2D:
- if (bind_generates_resource_) {
+ if (share_group_->bind_generates_resource()) {
*params = texture_units_[active_texture_unit_].bound_texture_2d;
return true;
}
return false;
case GL_TEXTURE_BINDING_CUBE_MAP:
- if (bind_generates_resource_) {
+ if (share_group_->bind_generates_resource()) {
*params = texture_units_[active_texture_unit_].bound_texture_cube_map;
return true;
}
return false;
case GL_FRAMEBUFFER_BINDING:
- if (bind_generates_resource_) {
+ if (share_group_->bind_generates_resource()) {
*params = bound_framebuffer_;
return true;
}
return false;
case GL_RENDERBUFFER_BINDING:
- if (bind_generates_resource_) {
+ if (share_group_->bind_generates_resource()) {
*params = bound_renderbuffer_;
return true;
}
@@ -1275,25 +1071,27 @@ void GLES2Implementation::GetVertexAttribPointerv(
}
bool GLES2Implementation::DeleteProgramHelper(GLuint program) {
- if (!id_handlers_[id_namespaces::kProgramsAndShaders]->FreeIds(1, &program)) {
+ if (!GetIdHandler(id_namespaces::kProgramsAndShaders)->FreeIds(
+ this, 1, &program)) {
SetGLError(
GL_INVALID_VALUE,
"glDeleteProgram: id not created by this context.");
return false;
}
- program_info_manager_->DeleteInfo(program);
+ share_group_->program_info_manager()->DeleteInfo(program);
helper_->DeleteProgram(program);
return true;
}
bool GLES2Implementation::DeleteShaderHelper(GLuint shader) {
- if (!id_handlers_[id_namespaces::kProgramsAndShaders]->FreeIds(1, &shader)) {
+ if (!GetIdHandler(id_namespaces::kProgramsAndShaders)->FreeIds(
+ this, 1, &shader)) {
SetGLError(
GL_INVALID_VALUE,
"glDeleteShader: id not created by this context.");
return false;
}
- program_info_manager_->DeleteInfo(shader);
+ share_group_->program_info_manager()->DeleteInfo(shader);
helper_->DeleteShader(shader);
return true;
}
@@ -1320,7 +1118,8 @@ GLint GLES2Implementation::GetAttribLocation(
GPU_CLIENT_LOG("[" << this << "] glGetAttribLocation(" << program
<< ", " << name << ")");
TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
- GLint loc = program_info_manager_->GetAttribLocation(this, program, name);
+ GLint loc = share_group_->program_info_manager()->GetAttribLocation(
+ this, program, name);
GPU_CLIENT_LOG("returned " << loc);
return loc;
}
@@ -1347,21 +1146,23 @@ GLint GLES2Implementation::GetUniformLocation(
GPU_CLIENT_LOG("[" << this << "] glGetUniformLocation(" << program
<< ", " << name << ")");
TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
- GLint loc = program_info_manager_->GetUniformLocation(this, program, name);
+ GLint loc = share_group_->program_info_manager()->GetUniformLocation(
+ this, program, name);
GPU_CLIENT_LOG("returned " << loc);
return loc;
}
bool GLES2Implementation::GetProgramivHelper(
GLuint program, GLenum pname, GLint* params) {
- return program_info_manager_->GetProgramiv(this, program, pname, params);
+ return share_group_->program_info_manager()->GetProgramiv(
+ this, program, pname, params);
}
void GLES2Implementation::LinkProgram(GLuint program) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << this << "] glLinkProgram(" << program << ")");
helper_->LinkProgram(program);
- program_info_manager_->CreateInfo(program);
+ share_group_->program_info_manager()->CreateInfo(program);
}
void GLES2Implementation::ShaderBinary(
@@ -1953,7 +1754,7 @@ void GLES2Implementation::GetActiveAttrib(
return;
}
TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
- bool success = program_info_manager_->GetActiveAttrib(
+ bool success = share_group_->program_info_manager()->GetActiveAttrib(
this, program, index, bufsize, length, size, type, name);
if (success) {
if (size) {
@@ -2023,7 +1824,7 @@ void GLES2Implementation::GetActiveUniform(
return;
}
TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
- bool success = program_info_manager_->GetActiveUniform(
+ bool success = share_group_->program_info_manager()->GetActiveUniform(
this, program, index, bufsize, length, size, type, name);
if (success) {
if (size) {
@@ -2343,7 +2144,7 @@ void GLES2Implementation::BindBufferHelper(
}
// TODO(gman): There's a bug here. If the target is invalid the ID will not be
// used even though it's marked it as used here.
- id_handlers_[id_namespaces::kBuffers]->MarkAsUsedForBind(buffer);
+ GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer);
}
void GLES2Implementation::BindFramebufferHelper(
@@ -2358,7 +2159,7 @@ void GLES2Implementation::BindFramebufferHelper(
}
// TODO(gman): There's a bug here. If the target is invalid the ID will not be
// used even though it's marked it as used here.
- id_handlers_[id_namespaces::kFramebuffers]->MarkAsUsedForBind(framebuffer);
+ GetIdHandler(id_namespaces::kFramebuffers)->MarkAsUsedForBind(framebuffer);
}
void GLES2Implementation::BindRenderbufferHelper(
@@ -2373,7 +2174,7 @@ void GLES2Implementation::BindRenderbufferHelper(
}
// TODO(gman): There's a bug here. If the target is invalid the ID will not be
// used even though it's marked it as used here.
- id_handlers_[id_namespaces::kRenderbuffers]->MarkAsUsedForBind(renderbuffer);
+ GetIdHandler(id_namespaces::kRenderbuffers)->MarkAsUsedForBind(renderbuffer);
}
void GLES2Implementation::BindTextureHelper(GLenum target, GLuint texture) {
@@ -2391,7 +2192,7 @@ void GLES2Implementation::BindTextureHelper(GLenum target, GLuint texture) {
}
// TODO(gman): There's a bug here. If the target is invalid the ID will not be
// used. even though it's marked it as used here.
- id_handlers_[id_namespaces::kTextures]->MarkAsUsedForBind(texture);
+ GetIdHandler(id_namespaces::kTextures)->MarkAsUsedForBind(texture);
}
#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
@@ -2411,7 +2212,7 @@ bool GLES2Implementation::IsBufferReservedId(GLuint /* id */) {
void GLES2Implementation::DeleteBuffersHelper(
GLsizei n, const GLuint* buffers) {
- if (!id_handlers_[id_namespaces::kBuffers]->FreeIds(n, buffers)) {
+ if (!GetIdHandler(id_namespaces::kBuffers)->FreeIds(this, n, buffers)) {
SetGLError(
GL_INVALID_VALUE,
"glDeleteBuffers: id not created by this context.");
@@ -2430,7 +2231,8 @@ void GLES2Implementation::DeleteBuffersHelper(
void GLES2Implementation::DeleteFramebuffersHelper(
GLsizei n, const GLuint* framebuffers) {
- if (!id_handlers_[id_namespaces::kFramebuffers]->FreeIds(n, framebuffers)) {
+ if (!GetIdHandler(id_namespaces::kFramebuffers)->FreeIds(
+ this, n, framebuffers)) {
SetGLError(
GL_INVALID_VALUE,
"glDeleteFramebuffers: id not created by this context.");
@@ -2446,7 +2248,8 @@ void GLES2Implementation::DeleteFramebuffersHelper(
void GLES2Implementation::DeleteRenderbuffersHelper(
GLsizei n, const GLuint* renderbuffers) {
- if (!id_handlers_[id_namespaces::kRenderbuffers]->FreeIds(n, renderbuffers)) {
+ if (!GetIdHandler(id_namespaces::kRenderbuffers)->FreeIds(
+ this, n, renderbuffers)) {
SetGLError(
GL_INVALID_VALUE,
"glDeleteRenderbuffers: id not created by this context.");
@@ -2462,7 +2265,8 @@ void GLES2Implementation::DeleteRenderbuffersHelper(
void GLES2Implementation::DeleteTexturesHelper(
GLsizei n, const GLuint* textures) {
- if (!id_handlers_[id_namespaces::kTextures]->FreeIds(n, textures)) {
+ if (!GetIdHandler(id_namespaces::kTextures)->FreeIds(
+ this, n, textures)) {
SetGLError(
GL_INVALID_VALUE,
"glDeleteTextures: id not created by this context.");
@@ -2991,7 +2795,8 @@ void GLES2Implementation::PostSubBufferCHROMIUM(
void GLES2Implementation::DeleteQueriesEXTHelper(
GLsizei n, const GLuint* queries) {
- if (!id_handlers_[id_namespaces::kQueries]->FreeIds(n, queries)) {
+ if (!GetIdHandler(id_namespaces::kQueries)->FreeIds(
+ this, n, queries)) {
SetGLError(
GL_INVALID_VALUE,
"glDeleteTextures: id not created by this context.");
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 352a947..ba1aef8 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -19,6 +19,7 @@
#include "../client/gles2_cmd_helper.h"
#include "../client/query_tracker.h"
#include "../client/ring_buffer.h"
+#include "../client/share_group.h"
#include "gles2_impl_export.h"
#if !defined(NDEBUG) && !defined(__native_client__) && !defined(GLES2_CONFORMANCE_TESTS) // NOLINT
@@ -83,24 +84,6 @@ class TransferBufferInterface;
namespace gles2 {
class ClientSideBufferHelper;
-class ProgramInfoManager;
-class ShareGroup;
-
-// Base class for IdHandlers
-class IdHandlerInterface {
- public:
- IdHandlerInterface() { }
- virtual ~IdHandlerInterface() { }
-
- // Makes some ids at or above id_offset.
- virtual void MakeIds(GLuint id_offset, GLsizei n, GLuint* ids) = 0;
-
- // Frees some ids.
- virtual bool FreeIds(GLsizei n, const GLuint* ids) = 0;
-
- // Marks an id as used for glBind functions. id = 0 does nothing.
- virtual bool MarkAsUsedForBind(GLuint id) = 0;
-};
// This class emulates GLES2 over command buffers. It can be used by a client
// program so that the program does not need deal with shared memory and command
@@ -209,15 +192,8 @@ class GLES2_IMPL_EXPORT GLES2Implementation {
GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
GLint* size, GLenum* type, char* name);
- GLuint MakeTextureId() {
- GLuint id;
- id_handlers_[id_namespaces::kTextures]->MakeIds(0, 1, &id);
- return id;
- }
-
- void FreeTextureId(GLuint id) {
- id_handlers_[id_namespaces::kTextures]->FreeIds(1, &id);
- }
+ GLuint MakeTextureId();
+ void FreeTextureId(GLuint id);
void SetSharedMemoryChunkSizeMultiple(unsigned int multiple);
@@ -454,10 +430,11 @@ class GLES2_IMPL_EXPORT GLES2Implementation {
bool IsExtensionAvailable(const char* ext);
+ IdHandlerInterface* GetIdHandler(int id_namespace) const;
+
GLES2Util util_;
GLES2CmdHelper* helper_;
TransferBufferInterface* transfer_buffer_;
- scoped_ptr<IdHandlerInterface> id_handlers_[id_namespaces::kNumIdNamespaces];
std::string last_error_;
std::queue<int32> swap_buffers_tokens_;
@@ -509,11 +486,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation {
// Whether or not to print debugging info.
bool debug_;
- // Whether or not this context is sharing resources.
- bool sharing_resources_;
-
- bool bind_generates_resource_;
-
// Used to check for single threaded access.
int use_count_;
@@ -534,8 +506,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation {
scoped_ptr<MappedMemoryManager> mapped_memory_;
- scoped_ptr<ProgramInfoManager> program_info_manager_;
-
scoped_refptr<ShareGroup> share_group_;
scoped_ptr<QueryTracker> query_tracker_;
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 495a913..dbebd67 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -206,8 +206,8 @@ GLuint CreateProgram() {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << this << "] glCreateProgram(" << ")");
GLuint client_id;
- id_handlers_[id_namespaces::kProgramsAndShaders]->
- MakeIds(0, 1, &client_id);
+ GetIdHandler(id_namespaces::kProgramsAndShaders)->
+ MakeIds(this, 0, 1, &client_id);
helper_->CreateProgram(client_id);
GPU_CLIENT_LOG("returned " << client_id);
return client_id;
@@ -217,8 +217,8 @@ GLuint CreateShader(GLenum type) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << this << "] glCreateShader(" << GLES2Util::GetStringShaderType(type) << ")"); // NOLINT
GLuint client_id;
- id_handlers_[id_namespaces::kProgramsAndShaders]->
- MakeIds(0, 1, &client_id);
+ GetIdHandler(id_namespaces::kProgramsAndShaders)->
+ MakeIds(this, 0, 1, &client_id);
helper_->CreateShader(type, client_id);
GPU_CLIENT_LOG("returned " << client_id);
return client_id;
@@ -402,8 +402,8 @@ void GenBuffers(GLsizei n, GLuint* buffers) {
return;
}
GPU_CLIENT_SINGLE_THREAD_CHECK();
- id_handlers_[id_namespaces::kBuffers]->
- MakeIds(0, n, buffers);
+ GetIdHandler(id_namespaces::kBuffers)->
+ MakeIds(this, 0, n, buffers);
helper_->GenBuffersImmediate(n, buffers);
GPU_CLIENT_LOG_CODE_BLOCK({
for (GLsizei i = 0; i < n; ++i) {
@@ -425,8 +425,8 @@ void GenFramebuffers(GLsizei n, GLuint* framebuffers) {
return;
}
GPU_CLIENT_SINGLE_THREAD_CHECK();
- id_handlers_[id_namespaces::kFramebuffers]->
- MakeIds(0, n, framebuffers);
+ GetIdHandler(id_namespaces::kFramebuffers)->
+ MakeIds(this, 0, n, framebuffers);
helper_->GenFramebuffersImmediate(n, framebuffers);
GPU_CLIENT_LOG_CODE_BLOCK({
for (GLsizei i = 0; i < n; ++i) {
@@ -442,8 +442,8 @@ void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
return;
}
GPU_CLIENT_SINGLE_THREAD_CHECK();
- id_handlers_[id_namespaces::kRenderbuffers]->
- MakeIds(0, n, renderbuffers);
+ GetIdHandler(id_namespaces::kRenderbuffers)->
+ MakeIds(this, 0, n, renderbuffers);
helper_->GenRenderbuffersImmediate(n, renderbuffers);
GPU_CLIENT_LOG_CODE_BLOCK({
for (GLsizei i = 0; i < n; ++i) {
@@ -459,8 +459,8 @@ void GenTextures(GLsizei n, GLuint* textures) {
return;
}
GPU_CLIENT_SINGLE_THREAD_CHECK();
- id_handlers_[id_namespaces::kTextures]->
- MakeIds(0, n, textures);
+ GetIdHandler(id_namespaces::kTextures)->
+ MakeIds(this, 0, n, textures);
helper_->GenTexturesImmediate(n, textures);
GPU_CLIENT_LOG_CODE_BLOCK({
for (GLsizei i = 0; i < n; ++i) {
@@ -1416,8 +1416,8 @@ void GenQueriesEXT(GLsizei n, GLuint* queries) {
return;
}
GPU_CLIENT_SINGLE_THREAD_CHECK();
- id_handlers_[id_namespaces::kQueries]->
- MakeIds(0, n, queries);
+ GetIdHandler(id_namespaces::kQueries)->
+ MakeIds(this, 0, n, queries);
helper_->GenQueriesEXTImmediate(n, queries);
GPU_CLIENT_LOG_CODE_BLOCK({
for (GLsizei i = 0; i < n; ++i) {
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
index 57a037d..d953914 100644
--- a/gpu/command_buffer/client/program_info_manager.cc
+++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -1,8 +1,9 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "../client/program_info_manager.h"
+#include "../client/atomicops.h"
#include "../client/gles2_implementation.h"
#include <map>
@@ -193,6 +194,8 @@ class CachedProgramInfoManager : public ProgramInfoManager {
typedef std::map<GLuint, ProgramInfo> ProgramInfoMap;
ProgramInfoMap program_infos_;
+
+ mutable Lock lock_;
};
CachedProgramInfoManager::ProgramInfo::UniformInfo::UniformInfo(
@@ -372,6 +375,7 @@ CachedProgramInfoManager::ProgramInfo*
}
void CachedProgramInfoManager::CreateInfo(GLuint program) {
+ AutoLock auto_lock(lock_);
DeleteInfo(program);
std::pair<ProgramInfoMap::iterator, bool> result =
program_infos_.insert(std::make_pair(program, ProgramInfo()));
@@ -385,6 +389,7 @@ void CachedProgramInfoManager::DeleteInfo(GLuint program) {
bool CachedProgramInfoManager::GetProgramiv(
GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
+ AutoLock auto_lock(lock_);
ProgramInfo* info = GetProgramInfo(gl, program);
if (!info) {
return false;
@@ -394,6 +399,7 @@ bool CachedProgramInfoManager::GetProgramiv(
GLint CachedProgramInfoManager::GetAttribLocation(
GLES2Implementation* gl, GLuint program, const char* name) {
+ AutoLock auto_lock(lock_);
ProgramInfo* info = GetProgramInfo(gl, program);
if (info) {
return info->GetAttribLocation(name);
@@ -403,6 +409,7 @@ GLint CachedProgramInfoManager::GetAttribLocation(
GLint CachedProgramInfoManager::GetUniformLocation(
GLES2Implementation* gl, GLuint program, const char* name) {
+ AutoLock auto_lock(lock_);
ProgramInfo* info = GetProgramInfo(gl, program);
if (info) {
return info->GetUniformLocation(name);
@@ -414,6 +421,7 @@ bool CachedProgramInfoManager::GetActiveAttrib(
GLES2Implementation* gl,
GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
GLint* size, GLenum* type, char* name) {
+ AutoLock auto_lock(lock_);
ProgramInfo* info = GetProgramInfo(gl, program);
if (info) {
const ProgramInfo::VertexAttribInfo* attrib_info =
@@ -448,6 +456,7 @@ bool CachedProgramInfoManager::GetActiveUniform(
GLES2Implementation* gl,
GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
GLint* size, GLenum* type, char* name) {
+ AutoLock auto_lock(lock_);
ProgramInfo* info = GetProgramInfo(gl, program);
if (info) {
const ProgramInfo::UniformInfo* uniform_info = info->GetUniformInfo(index);
diff --git a/gpu/command_buffer/client/share_group.cc b/gpu/command_buffer/client/share_group.cc
index 3e3b7e6..98b13c5 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
diff --git a/gpu/command_buffer/client/share_group.h b/gpu/command_buffer/client/share_group.h
index 8ce940a..cf3c44b 100644
--- a/gpu/command_buffer/client/share_group.h
+++ b/gpu/command_buffer/client/share_group.h
@@ -5,24 +5,79 @@
#ifndef GPU_COMMAND_BUFFER_CLIENT_SHARE_GROUP_H_
#define GPU_COMMAND_BUFFER_CLIENT_SHARE_GROUP_H_
+#include <GLES2/gl2.h>
#include "../client/ref_counted.h"
+#include "../common/gles2_cmd_format.h"
+#include "../common/scoped_ptr.h"
#include "gles2_impl_export.h"
namespace gpu {
namespace gles2 {
+class GLES2Implementation;
+class ProgramInfoManager;
+
+// Base class for IdHandlers
+class IdHandlerInterface {
+ public:
+ IdHandlerInterface() { }
+ virtual ~IdHandlerInterface() { }
+
+ // Free everything.
+ virtual void Destroy(GLES2Implementation* gl_impl) = 0;
+
+ // Makes some ids at or above id_offset.
+ virtual void MakeIds(
+ GLES2Implementation* gl_impl,
+ GLuint id_offset, GLsizei n, GLuint* ids) = 0;
+
+ // Frees some ids.
+ virtual bool FreeIds(
+ GLES2Implementation* gl_impl, GLsizei n, const GLuint* ids) = 0;
+
+ // Marks an id as used for glBind functions. id = 0 does nothing.
+ virtual bool MarkAsUsedForBind(GLuint id) = 0;
+};
+
// ShareGroup manages shared resources for contexts that are sharing resources.
class GLES2_IMPL_EXPORT ShareGroup
: public gpu::RefCountedThreadSafe<ShareGroup> {
public:
typedef scoped_refptr<ShareGroup> Ref;
- ShareGroup();
+ ShareGroup(bool share_resources, bool bind_generates_resource);
~ShareGroup();
+ void SetGLES2ImplementationForDestruction(GLES2Implementation* gl_impl);
+
+ bool sharing_resources() const {
+ return sharing_resources_;
+ }
+
+ bool bind_generates_resource() const {
+ return bind_generates_resource_;
+ }
+
bool Initialize();
+ IdHandlerInterface* GetIdHandler(int namespace_id) const {
+ return id_handlers_[namespace_id].get();
+ }
+
+ ProgramInfoManager* program_info_manager() {
+ return program_info_manager_.get();
+ }
+
private:
+ scoped_ptr<IdHandlerInterface> id_handlers_[id_namespaces::kNumIdNamespaces];
+ scoped_ptr<ProgramInfoManager> program_info_manager_;
+
+ // Whether or not this context is sharing resources.
+ bool sharing_resources_;
+ bool bind_generates_resource_;
+
+ GLES2Implementation* gles2_;
+
DISALLOW_COPY_AND_ASSIGN(ShareGroup);
};
diff --git a/gpu/command_buffer/client/share_group_unittest.cc b/gpu/command_buffer/client/share_group_unittest.cc
index e0e643e..053cbfa 100644
--- a/gpu/command_buffer/client/share_group_unittest.cc
+++ b/gpu/command_buffer/client/share_group_unittest.cc
@@ -16,7 +16,7 @@ class ShareGroupTest : public testing::Test {
protected:
virtual void SetUp() {
- share_group_ = ShareGroup::Ref(new ShareGroup());
+ share_group_ = ShareGroup::Ref(new ShareGroup(false, false));
}
virtual void TearDown() {