summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-03 19:14:10 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-03 19:14:10 +0000
commit066849e369dae48bf61ae0cf70c9e9acaf9f1045 (patch)
tree479aebcba9d2f1d3b054dc3ea64baa9a7c753f15
parent0411509f65aae2b1ba684bf87343a14253246de0 (diff)
downloadchromium_src-066849e369dae48bf61ae0cf70c9e9acaf9f1045.zip
chromium_src-066849e369dae48bf61ae0cf70c9e9acaf9f1045.tar.gz
chromium_src-066849e369dae48bf61ae0cf70c9e9acaf9f1045.tar.bz2
Adds support for shared resources.
It's not clear how to test this easily it seems like we an integration test is needed at some point. I did run the conformance tests with share_resources set to true and it rand without crashing. TEST=unit tests BUG=none Review URL: http://codereview.chromium.org/1817002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46264 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/renderer/ggl/ggl.cc3
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py65
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h11
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h21
-rw-r--r--gpu/command_buffer/client/gles2_demo.cc3
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc158
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h52
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h39
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc4
-rw-r--r--gpu/command_buffer/client/ring_buffer.h14
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format.h20
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h158
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h59
-rw-r--r--gpu/command_buffer/common/gles2_cmd_id_test_autogen.h6
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h3
-rw-r--r--gpu/command_buffer/common/id_allocator.cc (renamed from gpu/command_buffer/client/id_allocator.cc)12
-rw-r--r--gpu/command_buffer/common/id_allocator.h (renamed from gpu/command_buffer/client/id_allocator.h)8
-rw-r--r--gpu/command_buffer/common/id_allocator_test.cc (renamed from gpu/command_buffer/client/id_allocator_test.cc)16
-rw-r--r--gpu/command_buffer/docs/gles2_cmd_format_docs.txt35
-rw-r--r--gpu/command_buffer/service/context_group.cc11
-rw-r--r--gpu/command_buffer/service/context_group.h11
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc128
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc118
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h20
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h8
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h4
-rw-r--r--gpu/demos/framework/window.cc3
-rw-r--r--gpu/gpu.gyp6
-rw-r--r--gpu/pgl/pgl.cc3
29 files changed, 900 insertions, 99 deletions
diff --git a/chrome/renderer/ggl/ggl.cc b/chrome/renderer/ggl/ggl.cc
index a6f1314..1d2c14a 100644
--- a/chrome/renderer/ggl/ggl.cc
+++ b/chrome/renderer/ggl/ggl.cc
@@ -174,7 +174,8 @@ bool Context::Initialize(gfx::NativeViewId view, const gfx::Size& size) {
gles2_helper_,
transfer_buffer.size,
transfer_buffer.ptr,
- transfer_buffer_id_);
+ transfer_buffer_id_,
+ false);
return true;
}
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 1a74b4e..b22a304 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -178,6 +178,9 @@ GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width,
// Non-GL commands.
GL_APICALL void GL_APIENTRY glSwapBuffers (void);
GL_APICALL GLuint GL_APIENTRY glGetMaxValueInBuffer (GLidBuffer buffer_id, GLsizei count, GLenumIndexType type, GLuint offset);
+GL_APICALL void GL_APIENTRY glGenSharedIds (GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
+GL_APICALL void GL_APIENTRY glDeleteSharedIds (GLuint namespace_id, GLsizei n, const GLuint* ids);
+GL_APICALL void GL_APIENTRY glRegisterSharedIds (GLuint namespace_id, GLsizei n, const GLuint* ids);
"""
# This is the list of all commmands that will be generated and their Id.
@@ -369,6 +372,9 @@ _CMD_ID_TABLE = {
'ShaderBinary': 436,
'ReleaseShaderCompiler': 437,
'GetMaxValueInBuffer': 438,
+ 'GenSharedIds': 439,
+ 'DeleteSharedIds': 440,
+ 'RegisterSharedIds': 441,
}
# This is a list of enum names and their valid values. It is used to map
@@ -1006,12 +1012,19 @@ _FUNCTION_INFO = {
'type': 'DELn',
'gl_test_func': 'glDeleteFramebuffersEXT',
},
- 'DeleteProgram': {'type': 'Custom', 'decoder_func': 'DoDeleteProgram'},
+ 'DeleteProgram': {'type': 'Delete', 'decoder_func': 'DoDeleteProgram'},
'DeleteRenderbuffers': {
'type': 'DELn',
'gl_test_func': 'glDeleteRenderbuffersEXT',
},
- 'DeleteShader': {'type': 'Custom', 'decoder_func': 'DoDeleteShader'},
+ 'DeleteShader': {'type': 'Delete', 'decoder_func': 'DoDeleteShader'},
+ 'DeleteSharedIds': {
+ 'type': 'Custom',
+ 'decoder_func': 'DoDeleteSharedIds',
+ 'impl_func': False,
+ 'expectation': False,
+ 'immediate': False,
+ },
'DeleteTextures': {'type': 'DELn'},
'DepthRangef': {'decoder_func': 'glDepthRange'},
'DetachShader': {'decoder_func': 'DoDetachShader'},
@@ -1054,6 +1067,13 @@ _FUNCTION_INFO = {
'GenFramebuffers': {'type': 'GENn', 'gl_test_func': 'glGenFramebuffersEXT'},
'GenRenderbuffers': {'type': 'GENn', 'gl_test_func': 'glGenRenderbuffersEXT'},
'GenTextures': {'type': 'GENn', 'gl_test_func': 'glGenTextures'},
+ 'GenSharedIds': {
+ 'type': 'Custom',
+ 'decoder_func': 'DoGenSharedIds',
+ 'impl_func': False,
+ 'expectation': False,
+ 'immediate': False,
+ },
'GetActiveAttrib': {
'type': 'Custom',
'immediate': False,
@@ -1263,6 +1283,13 @@ _FUNCTION_INFO = {
'uint32 result_shm_id, uint32 result_shm_offset',
'result': ['uint32'],
},
+ 'RegisterSharedIds': {
+ 'type': 'Custom',
+ 'decoder_func': 'DoRegisterSharedIds',
+ 'impl_func': False,
+ 'expectation': False,
+ 'immediate': False,
+ },
'ReleaseShaderCompiler': {
'decoder_func': 'DoReleaseShaderCompiler',
'unit_test': False,
@@ -2206,9 +2233,7 @@ TEST_F(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
SetGLError(GL_INVALID_OPERATION, "%(name)s: %(id)s reserved id");
return;
}
- if (%(id)s != 0) {
- %(lc_type)s_id_allocator_.MarkAsUsed(%(id)s);
- }
+ %(lc_type)s_id_handler_->MarkAsUsedForBind(%(id)s);
helper_->%(name)s(%(arg_string)s);
}
@@ -2260,7 +2285,7 @@ class GENnHandler(TypeHandler):
def WriteGLES2ImplementationHeader(self, func, file):
"""Overrriden from TypeHandler."""
code = """%(return_type)s %(name)s(%(typed_args)s) {
- MakeIds(&%(resource_type)s_id_allocator_, %(args)s);
+ %(resource_type)s_id_handler_->MakeIds(0, %(args)s);
helper_->%(name)sImmediate(%(args)s);
}
@@ -2493,7 +2518,7 @@ TEST_F(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
(func.return_type, func.original_name,
func.MakeTypedOriginalArgString("")))
file.Write(" GLuint client_id;\n")
- file.Write(" MakeIds(&program_and_shader_id_allocator_, 1, &client_id);\n")
+ file.Write(" program_and_shader_id_handler_->MakeIds(0, 1, &client_id);\n")
file.Write(" helper_->%s(%s);\n" %
(func.name, func.MakeCmdArgString("")))
file.Write(" return client_id;\n")
@@ -2501,6 +2526,29 @@ TEST_F(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
file.Write("\n")
+class DeleteHandler(TypeHandler):
+ """Handler for glDelete___ single resource type functions."""
+
+ def __init__(self):
+ TypeHandler.__init__(self)
+
+ def WriteServiceImplementation(self, func, file):
+ """Overrriden from TypeHandler."""
+ pass
+
+ def WriteGLES2ImplementationHeader(self, func, file):
+ """Overrriden from TypeHandler."""
+ file.Write("%s %s(%s) {\n" %
+ (func.return_type, func.original_name,
+ func.MakeTypedOriginalArgString("")))
+ file.Write(" program_and_shader_id_handler_->FreeIds(1, &%s);\n" %
+ func.GetOriginalArgs()[-1].name)
+ file.Write(" helper_->%s(%s);\n" %
+ (func.name, func.MakeCmdArgString("")))
+ file.Write("}\n")
+ file.Write("\n")
+
+
class DELnHandler(TypeHandler):
"""Handler for glDelete___ type functions."""
@@ -2602,7 +2650,7 @@ TEST_F(%(test_name)s, %(name)sInvalidArgs) {
file.Write("%s %s(%s) {\n" %
(func.return_type, func.original_name,
func.MakeTypedOriginalArgString("")))
- file.Write(" FreeIds(&%s_id_allocator_, %s);\n" %
+ file.Write(" %s_id_handler_->FreeIds(%s);\n" %
(func.name[6:-1].lower(), func.MakeOriginalArgString("")))
file.Write(" helper_->%sImmediate(%s);\n" %
(func.name, func.MakeOriginalArgString("")))
@@ -4349,6 +4397,7 @@ class GLGenerator(object):
'Create': CreateHandler(),
'Custom': CustomHandler(),
'Data': DataHandler(),
+ 'Delete': DeleteHandler(),
'DELn': DELnHandler(),
'GENn': GENnHandler(),
'GETn': GETnHandler(),
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index c3e445a..73cd6ce 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -508,6 +508,17 @@ GLuint GLES2GetMaxValueInBuffer(
return gles2::GetGLContext()->GetMaxValueInBuffer(
buffer_id, count, type, offset);
}
+void GLES2GenSharedIds(
+ GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
+ gles2::GetGLContext()->GenSharedIds(namespace_id, id_offset, n, ids);
+}
+void GLES2DeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids) {
+ gles2::GetGLContext()->DeleteSharedIds(namespace_id, n, ids);
+}
+void GLES2RegisterSharedIds(
+ GLuint namespace_id, GLsizei n, const GLuint* ids) {
+ gles2::GetGLContext()->RegisterSharedIds(namespace_id, n, ids);
+}
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_C_LIB_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index bb37150..652579d 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -1127,5 +1127,26 @@
c.Init(buffer_id, count, type, offset, result_shm_id, result_shm_offset);
}
+ void GenSharedIds(
+ GLuint namespace_id, GLuint id_offset, GLsizei n, uint32 ids_shm_id,
+ uint32 ids_shm_offset) {
+ gles2::GenSharedIds& c = GetCmdSpace<gles2::GenSharedIds>();
+ c.Init(namespace_id, id_offset, n, ids_shm_id, ids_shm_offset);
+ }
+
+ void DeleteSharedIds(
+ GLuint namespace_id, GLsizei n, uint32 ids_shm_id,
+ uint32 ids_shm_offset) {
+ gles2::DeleteSharedIds& c = GetCmdSpace<gles2::DeleteSharedIds>();
+ c.Init(namespace_id, n, ids_shm_id, ids_shm_offset);
+ }
+
+ void RegisterSharedIds(
+ GLuint namespace_id, GLsizei n, uint32 ids_shm_id,
+ uint32 ids_shm_offset) {
+ gles2::RegisterSharedIds& c = GetCmdSpace<gles2::RegisterSharedIds>();
+ c.Init(namespace_id, n, ids_shm_id, ids_shm_offset);
+ }
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc
index 3e9ea77..b2a0497 100644
--- a/gpu/command_buffer/client/gles2_demo.cc
+++ b/gpu/command_buffer/client/gles2_demo.cc
@@ -84,7 +84,8 @@ bool GLES2Demo::Setup(void* hwnd, int32 size) {
gles2::SetGLContext(new GLES2Implementation(helper,
transfer_buffer.size,
transfer_buffer.ptr,
- transfer_buffer_id));
+ transfer_buffer_id,
+ false));
GLFromCPPInit();
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 3886b95..551e361 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -6,6 +6,7 @@
#include "../client/gles2_implementation.h"
#include "../common/gles2_cmd_utils.h"
+#include "../common/id_allocator.h"
namespace gpu {
namespace gles2 {
@@ -21,6 +22,71 @@ static GLsizei RoundUpToMultipleOf4(GLsizei size) {
return (size + 3) & ~3;
}
+// 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 void FreeIds(GLsizei n, const GLuint* ids) {
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ id_allocator_.FreeID(ids[ii]);
+ }
+ }
+
+ // Overridden from IdHandlerInterface.
+ virtual bool MarkAsUsedForBind(GLuint id) {
+ return id == 0 ? true : id_allocator_.MarkAsUsed(id);
+ }
+ private:
+ IdAllocator id_allocator_;
+};
+
+// 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_->GenSharedIds(id_namespace_, id_offset, n, ids);
+ }
+
+ virtual void FreeIds(GLsizei n, const GLuint* ids) {
+ gles2_->DeleteSharedIds(id_namespace_, n, ids);
+ }
+
+ virtual bool MarkAsUsedForBind(GLuint) { // NOLINT
+ // This has no meaning for shared resources.
+ return true;
+ }
+
+ private:
+ GLES2Implementation* gles2_;
+ id_namespaces::IdNamespaces id_namespace_;
+};
+
// This class tracks VertexAttribPointers and helps emulate client side buffers.
//
// The way client side buffers work is we shadow all the Vertex Attribs so we
@@ -331,7 +397,8 @@ GLES2Implementation::GLES2Implementation(
GLES2CmdHelper* helper,
size_t transfer_buffer_size,
void* transfer_buffer,
- int32 transfer_buffer_id)
+ int32 transfer_buffer_id,
+ bool share_resources)
: util_(0), // TODO(gman): Get real number of compressed texture formats.
helper_(helper),
transfer_buffer_(
@@ -345,45 +412,49 @@ GLES2Implementation::GLES2Implementation(
#if defined(GLES2_SUPPORT_CLIENT_SIDE_BUFFERS)
bound_array_buffer_id_(0),
bound_element_array_buffer_id_(0),
+ client_side_array_id_(0),
+ client_side_element_array_id_(0),
#endif
error_bits_(0) {
// Allocate space for simple GL results.
result_buffer_ = transfer_buffer;
result_shm_offset_ = 0;
+ if (share_resources) {
+ buffer_id_handler_.reset(
+ new SharedIdHandler(this, id_namespaces::kBuffers));
+ framebuffer_id_handler_.reset(
+ new SharedIdHandler(this, id_namespaces::kFramebuffers));
+ renderbuffer_id_handler_.reset(
+ new SharedIdHandler(this, id_namespaces::kRenderbuffers));
+ program_and_shader_id_handler_.reset(
+ new SharedIdHandler(this, id_namespaces::kProgramsAndShaders));
+ texture_id_handler_.reset(
+ new SharedIdHandler(this, id_namespaces::kTextures));
+ } else {
+ buffer_id_handler_.reset(new NonSharedIdHandler());
+ framebuffer_id_handler_.reset(new NonSharedIdHandler());
+ renderbuffer_id_handler_.reset(new NonSharedIdHandler());
+ program_and_shader_id_handler_.reset(new NonSharedIdHandler());
+ texture_id_handler_.reset(new NonSharedIdHandler());
+ }
+
#if defined(GLES2_SUPPORT_CLIENT_SIDE_BUFFERS)
GLint max_vertex_attribs;
GetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);
- buffer_id_allocator_.MarkAsUsed(kClientSideArrayId);
- buffer_id_allocator_.MarkAsUsed(kClientSideElementArrayId);
- reserved_ids_[0] = kClientSideArrayId;
- reserved_ids_[1] = kClientSideElementArrayId;
+ buffer_id_handler_->MakeIds(
+ kClientSideArrayId, arraysize(reserved_ids_), &reserved_ids_[0]);
client_side_buffer_helper_.reset(new ClientSideBufferHelper(
max_vertex_attribs,
- kClientSideArrayId,
- kClientSideElementArrayId));
+ reserved_ids_[0],
+ reserved_ids_[1]));
#endif
}
GLES2Implementation::~GLES2Implementation() {
- GLuint buffers[] = { kClientSideArrayId, kClientSideElementArrayId, };
- DeleteBuffers(arraysize(buffers), &buffers[0]);
-}
-
-void GLES2Implementation::MakeIds(
- IdAllocator* id_allocator, GLsizei n, GLuint* ids) {
- for (GLsizei ii = 0; ii < n; ++ii) {
- ids[ii] = id_allocator->AllocateID();
- }
-}
-
-void GLES2Implementation::FreeIds(
- IdAllocator* id_allocator, GLsizei n, const GLuint* ids) {
- for (GLsizei ii = 0; ii < n; ++ii) {
- id_allocator->FreeID(ids[ii]);
- }
+ DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]);
}
void GLES2Implementation::WaitForCmd() {
@@ -580,6 +651,39 @@ void GLES2Implementation::SwapBuffers() {
Flush();
}
+void GLES2Implementation::GenSharedIds(
+ GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
+ GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(n);
+ helper_->GenSharedIds(namespace_id, id_offset, n,
+ transfer_buffer_id_,
+ transfer_buffer_.GetOffset(id_buffer));
+ WaitForCmd();
+ memcpy(ids, id_buffer, sizeof(*ids) * n);
+ transfer_buffer_.FreePendingToken(id_buffer, helper_->InsertToken());
+}
+
+void GLES2Implementation::DeleteSharedIds(
+ GLuint namespace_id, GLsizei n, const GLuint* ids) {
+ GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(n);
+ memcpy(id_buffer, ids, sizeof(*ids) * n);
+ helper_->DeleteSharedIds(namespace_id, n,
+ transfer_buffer_id_,
+ transfer_buffer_.GetOffset(id_buffer));
+ WaitForCmd();
+ transfer_buffer_.FreePendingToken(id_buffer, helper_->InsertToken());
+}
+
+void GLES2Implementation::RegisterSharedIds(
+ GLuint namespace_id, GLsizei n, const GLuint* ids) {
+ GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(n);
+ memcpy(id_buffer, ids, sizeof(*ids) * n);
+ helper_->RegisterSharedIds(namespace_id, n,
+ transfer_buffer_id_,
+ transfer_buffer_.GetOffset(id_buffer));
+ WaitForCmd();
+ transfer_buffer_.FreePendingToken(id_buffer, helper_->InsertToken());
+}
+
void GLES2Implementation::BindAttribLocation(
GLuint program, GLuint index, const char* name) {
SetBucketAsString(kResultBucketId, name);
@@ -1155,7 +1259,7 @@ void GLES2Implementation::ReadPixels(
}
transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken());
// If it was not marked as successful exit.
- if (*result == 0) {
+ if (*result != 0) {
return;
}
yoffset += num_rows;
@@ -1222,9 +1326,7 @@ void GLES2Implementation::BindBuffer(GLenum target, GLuint buffer) {
SetGLError(GL_INVALID_OPERATION, "glBindBuffer: reserved buffer id");
return;
}
- if (buffer != 0) {
- buffer_id_allocator_.MarkAsUsed(buffer);
- }
+ buffer_id_handler_->MarkAsUsedForBind(buffer);
switch (target) {
case GL_ARRAY_BUFFER:
bound_array_buffer_id_ = buffer;
@@ -1239,7 +1341,7 @@ void GLES2Implementation::BindBuffer(GLenum target, GLuint buffer) {
}
void GLES2Implementation::DeleteBuffers(GLsizei n, const GLuint* buffers) {
- FreeIds(&buffer_id_allocator_, n, buffers);
+ buffer_id_handler_->FreeIds(n, buffers);
for (GLsizei ii = 0; ii < n; ++ii) {
if (buffers[ii] == bound_array_buffer_id_) {
bound_array_buffer_id_ = 0;
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 4d0e53e..5ff41a2 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -11,7 +11,6 @@
#include "../common/gles2_cmd_utils.h"
#include "../common/scoped_ptr.h"
#include "../client/gles2_cmd_helper.h"
-#include "../client/id_allocator.h"
#include "../client/ring_buffer.h"
#define GLES2_SUPPORT_CLIENT_SIDE_BUFFERS 1
@@ -21,6 +20,22 @@ namespace gles2 {
class ClientSideBufferHelper;
+// 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 void 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
// buffer management. See gl2_lib.h. Note that there is a performance gain to
@@ -49,7 +64,8 @@ class GLES2Implementation {
GLES2CmdHelper* helper,
size_t transfer_buffer_size,
void* transfer_buffer,
- int32 transfer_buffer_id);
+ int32 transfer_buffer_id,
+ bool share_resources);
~GLES2Implementation();
@@ -126,17 +142,15 @@ class GLES2Implementation {
}
#endif
- void MakeIds(IdAllocator* id_allocator, GLsizei n, GLuint* ids);
+ GLuint MakeTextureId() {
+ GLuint id;
+ texture_id_handler_->MakeIds(0, 1, &id);
+ return id;
+ }
- void FreeIds(IdAllocator* id_allocator, GLsizei n, const GLuint* ids);
-
- GLuint MakeTextureId() {
- return texture_id_allocator_.AllocateID();
- }
-
- void FreeTextureId(GLuint id) {
- texture_id_allocator_.FreeID(id);
- }
+ void FreeTextureId(GLuint id) {
+ texture_id_handler_->FreeIds(1, &id);
+ }
private:
// Wraps RingBufferWrapper to provide aligned allocations.
@@ -231,11 +245,11 @@ class GLES2Implementation {
GLES2Util util_;
GLES2CmdHelper* helper_;
- IdAllocator buffer_id_allocator_;
- IdAllocator framebuffer_id_allocator_;
- IdAllocator renderbuffer_id_allocator_;
- IdAllocator program_and_shader_id_allocator_;
- IdAllocator texture_id_allocator_;
+ scoped_ptr<IdHandlerInterface> buffer_id_handler_;
+ scoped_ptr<IdHandlerInterface> framebuffer_id_handler_;
+ scoped_ptr<IdHandlerInterface> renderbuffer_id_handler_;
+ scoped_ptr<IdHandlerInterface> program_and_shader_id_handler_;
+ scoped_ptr<IdHandlerInterface> texture_id_handler_;
AlignedRingBuffer transfer_buffer_;
int transfer_buffer_id_;
void* result_buffer_;
@@ -255,6 +269,10 @@ class GLES2Implementation {
// The currently bound element array buffer.
GLuint bound_element_array_buffer_id_;
+ // GL names for the buffers used to emulate client side buffers.
+ GLuint client_side_array_id_;
+ GLuint client_side_element_array_id_;
+
// Info for each vertex attribute saved so we can simulate client side
// buffers.
scoped_ptr<ClientSideBufferHelper> client_side_buffer_helper_;
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 06bcdcc..63d0b53 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -25,9 +25,7 @@ void BindFramebuffer(GLenum target, GLuint framebuffer) {
GL_INVALID_OPERATION, "BindFramebuffer: framebuffer reserved id");
return;
}
- if (framebuffer != 0) {
- framebuffer_id_allocator_.MarkAsUsed(framebuffer);
- }
+ framebuffer_id_handler_->MarkAsUsedForBind(framebuffer);
helper_->BindFramebuffer(target, framebuffer);
}
@@ -37,9 +35,7 @@ void BindRenderbuffer(GLenum target, GLuint renderbuffer) {
GL_INVALID_OPERATION, "BindRenderbuffer: renderbuffer reserved id");
return;
}
- if (renderbuffer != 0) {
- renderbuffer_id_allocator_.MarkAsUsed(renderbuffer);
- }
+ renderbuffer_id_handler_->MarkAsUsedForBind(renderbuffer);
helper_->BindRenderbuffer(target, renderbuffer);
}
@@ -48,9 +44,7 @@ void BindTexture(GLenum target, GLuint texture) {
SetGLError(GL_INVALID_OPERATION, "BindTexture: texture reserved id");
return;
}
- if (texture != 0) {
- texture_id_allocator_.MarkAsUsed(texture);
- }
+ texture_id_handler_->MarkAsUsedForBind(texture);
helper_->BindTexture(target, texture);
}
@@ -156,14 +150,14 @@ void CopyTexSubImage2D(
GLuint CreateProgram() {
GLuint client_id;
- MakeIds(&program_and_shader_id_allocator_, 1, &client_id);
+ program_and_shader_id_handler_->MakeIds(0, 1, &client_id);
helper_->CreateProgram(client_id);
return client_id;
}
GLuint CreateShader(GLenum type) {
GLuint client_id;
- MakeIds(&program_and_shader_id_allocator_, 1, &client_id);
+ program_and_shader_id_handler_->MakeIds(0, 1, &client_id);
helper_->CreateShader(type, client_id);
return client_id;
}
@@ -173,25 +167,27 @@ void CullFace(GLenum mode) {
}
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
- FreeIds(&framebuffer_id_allocator_, n, framebuffers);
+ framebuffer_id_handler_->FreeIds(n, framebuffers);
helper_->DeleteFramebuffersImmediate(n, framebuffers);
}
void DeleteProgram(GLuint program) {
+ program_and_shader_id_handler_->FreeIds(1, &program);
helper_->DeleteProgram(program);
}
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
- FreeIds(&renderbuffer_id_allocator_, n, renderbuffers);
+ renderbuffer_id_handler_->FreeIds(n, renderbuffers);
helper_->DeleteRenderbuffersImmediate(n, renderbuffers);
}
void DeleteShader(GLuint shader) {
+ program_and_shader_id_handler_->FreeIds(1, &shader);
helper_->DeleteShader(shader);
}
void DeleteTextures(GLsizei n, const GLuint* textures) {
- FreeIds(&texture_id_allocator_, n, textures);
+ texture_id_handler_->FreeIds(n, textures);
helper_->DeleteTexturesImmediate(n, textures);
}
@@ -244,7 +240,7 @@ void FrontFace(GLenum mode) {
}
void GenBuffers(GLsizei n, GLuint* buffers) {
- MakeIds(&buffer_id_allocator_, n, buffers);
+ buffer_id_handler_->MakeIds(0, n, buffers);
helper_->GenBuffersImmediate(n, buffers);
}
@@ -253,17 +249,17 @@ void GenerateMipmap(GLenum target) {
}
void GenFramebuffers(GLsizei n, GLuint* framebuffers) {
- MakeIds(&framebuffer_id_allocator_, n, framebuffers);
+ framebuffer_id_handler_->MakeIds(0, n, framebuffers);
helper_->GenFramebuffersImmediate(n, framebuffers);
}
void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
- MakeIds(&renderbuffer_id_allocator_, n, renderbuffers);
+ renderbuffer_id_handler_->MakeIds(0, n, renderbuffers);
helper_->GenRenderbuffersImmediate(n, renderbuffers);
}
void GenTextures(GLsizei n, GLuint* textures) {
- MakeIds(&texture_id_allocator_, n, textures);
+ texture_id_handler_->MakeIds(0, n, textures);
helper_->GenTexturesImmediate(n, textures);
}
@@ -759,5 +755,12 @@ GLuint GetMaxValueInBuffer(
return *result;
}
+void GenSharedIds(
+ GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
+
+void DeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
+
+void RegisterSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 93710fc..e43bf84 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -152,7 +152,6 @@ class GLES2ImplementationTest : public testing::Test {
command_buffer_.reset(new MockGLES2CommandBuffer());
command_buffer_->Initialize(kNumCommandEntries);
-
EXPECT_EQ(kTransferBufferId,
command_buffer_->CreateTransferBuffer(kTransferBufferSize));
transfer_buffer_ = command_buffer_->GetTransferBuffer(kTransferBufferId);
@@ -171,7 +170,8 @@ class GLES2ImplementationTest : public testing::Test {
helper_.get(),
kTransferBufferSize,
transfer_buffer_.ptr,
- kTransferBufferId));
+ kTransferBufferId,
+ false));
EXPECT_CALL(*command_buffer_, OnFlush(_)).Times(1).RetiresOnSaturation();
helper_->CommandBufferHelper::Flush();
diff --git a/gpu/command_buffer/client/ring_buffer.h b/gpu/command_buffer/client/ring_buffer.h
index 0b55661..38ee912 100644
--- a/gpu/command_buffer/client/ring_buffer.h
+++ b/gpu/command_buffer/client/ring_buffer.h
@@ -128,7 +128,7 @@ class RingBufferWrapper {
// Returns:
// the pointer to the allocated memory block, or NULL if out of
// memory.
- void *Alloc(unsigned int size) {
+ void* Alloc(unsigned int size) {
RingBuffer::Offset offset = allocator_.Alloc(size);
return GetPointer(offset);
}
@@ -144,8 +144,8 @@ class RingBufferWrapper {
// Returns:
// the pointer to the allocated memory block, or NULL if out of
// memory.
- template <typename T> T *AllocTyped(unsigned int count) {
- return static_cast<T *>(Alloc(count * sizeof(T)));
+ template <typename T> T* AllocTyped(unsigned int count) {
+ return static_cast<T*>(Alloc(count * sizeof(T)));
}
// Frees a block of memory, pending the passage of a token. That memory won't
@@ -154,18 +154,18 @@ class RingBufferWrapper {
// Parameters:
// pointer: the pointer to the memory block to free.
// token: the token value to wait for before re-using the memory.
- void FreePendingToken(void *pointer, unsigned int token) {
+ void FreePendingToken(void* pointer, unsigned int token) {
DCHECK(pointer);
allocator_.FreePendingToken(GetOffset(pointer), token);
}
// Gets a pointer to a memory block given the base memory and the offset.
- void *GetPointer(RingBuffer::Offset offset) {
+ void* GetPointer(RingBuffer::Offset offset) {
return static_cast<int8*>(base_) + offset;
}
// Gets the offset to a memory block given the base memory and the address.
- RingBuffer::Offset GetOffset(void *pointer) {
+ RingBuffer::Offset GetOffset(void* pointer) {
return static_cast<int8*>(pointer) - static_cast<int8*>(base_);
}
@@ -182,7 +182,7 @@ class RingBufferWrapper {
private:
RingBuffer allocator_;
- void *base_;
+ void* base_;
RingBuffer::Offset base_offset_;
DISALLOW_IMPLICIT_CONSTRUCTORS(RingBufferWrapper);
};
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h
index 6935380..2be1e36 100644
--- a/gpu/command_buffer/common/gles2_cmd_format.h
+++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -39,6 +39,26 @@ namespace gles2 {
#pragma pack(push, 1)
+namespace id_namespaces {
+
+// These are used when contexts share resources.
+enum IdNamespaces {
+ kBuffers,
+ kFramebuffers,
+ kProgramsAndShaders,
+ kRenderbuffers,
+ kTextures,
+};
+
+// These numbers must not change
+COMPILE_ASSERT(kBuffers == 0, kBuffers_is_not_0);
+COMPILE_ASSERT(kFramebuffers == 1, kFramebuffers_is_not_1);
+COMPILE_ASSERT(kProgramsAndShaders == 2, kProgramsAndShaders_is_not_2);
+COMPILE_ASSERT(kRenderbuffers == 3, kRenderbuffers_is_not_3);
+COMPILE_ASSERT(kTextures == 4, kTextures_is_not_4);
+
+} // namespace id_namespaces
+
// Used for some glGetXXX commands that return a result through a pointer. We
// need to know if the command succeeded or not and the size of the result. If
// the command failed its result size will 0.
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index b6b8128..7e07dd7 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -8280,6 +8280,164 @@ COMPILE_ASSERT(offsetof(GetMaxValueInBuffer, result_shm_id) == 20,
COMPILE_ASSERT(offsetof(GetMaxValueInBuffer, result_shm_offset) == 24,
OffsetOf_GetMaxValueInBuffer_result_shm_offset_not_24);
+struct GenSharedIds {
+ typedef GenSharedIds ValueType;
+ static const CommandId kCmdId = kGenSharedIds;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+ static uint32 ComputeSize() {
+ return static_cast<uint32>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() {
+ header.SetCmd<ValueType>();
+ }
+
+ void Init(
+ GLuint _namespace_id, GLuint _id_offset, GLsizei _n, uint32 _ids_shm_id,
+ uint32 _ids_shm_offset) {
+ SetHeader();
+ namespace_id = _namespace_id;
+ id_offset = _id_offset;
+ n = _n;
+ ids_shm_id = _ids_shm_id;
+ ids_shm_offset = _ids_shm_offset;
+ }
+
+ void* Set(
+ void* cmd, GLuint _namespace_id, GLuint _id_offset, GLsizei _n,
+ uint32 _ids_shm_id, uint32 _ids_shm_offset) {
+ static_cast<ValueType*>(
+ cmd)->Init(
+ _namespace_id, _id_offset, _n, _ids_shm_id, _ids_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32 namespace_id;
+ uint32 id_offset;
+ int32 n;
+ uint32 ids_shm_id;
+ uint32 ids_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(GenSharedIds) == 24,
+ Sizeof_GenSharedIds_is_not_24);
+COMPILE_ASSERT(offsetof(GenSharedIds, header) == 0,
+ OffsetOf_GenSharedIds_header_not_0);
+COMPILE_ASSERT(offsetof(GenSharedIds, namespace_id) == 4,
+ OffsetOf_GenSharedIds_namespace_id_not_4);
+COMPILE_ASSERT(offsetof(GenSharedIds, id_offset) == 8,
+ OffsetOf_GenSharedIds_id_offset_not_8);
+COMPILE_ASSERT(offsetof(GenSharedIds, n) == 12,
+ OffsetOf_GenSharedIds_n_not_12);
+COMPILE_ASSERT(offsetof(GenSharedIds, ids_shm_id) == 16,
+ OffsetOf_GenSharedIds_ids_shm_id_not_16);
+COMPILE_ASSERT(offsetof(GenSharedIds, ids_shm_offset) == 20,
+ OffsetOf_GenSharedIds_ids_shm_offset_not_20);
+
+struct DeleteSharedIds {
+ typedef DeleteSharedIds ValueType;
+ static const CommandId kCmdId = kDeleteSharedIds;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+ static uint32 ComputeSize() {
+ return static_cast<uint32>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() {
+ header.SetCmd<ValueType>();
+ }
+
+ void Init(
+ GLuint _namespace_id, GLsizei _n, uint32 _ids_shm_id,
+ uint32 _ids_shm_offset) {
+ SetHeader();
+ namespace_id = _namespace_id;
+ n = _n;
+ ids_shm_id = _ids_shm_id;
+ ids_shm_offset = _ids_shm_offset;
+ }
+
+ void* Set(
+ void* cmd, GLuint _namespace_id, GLsizei _n, uint32 _ids_shm_id,
+ uint32 _ids_shm_offset) {
+ static_cast<ValueType*>(
+ cmd)->Init(_namespace_id, _n, _ids_shm_id, _ids_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32 namespace_id;
+ int32 n;
+ uint32 ids_shm_id;
+ uint32 ids_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(DeleteSharedIds) == 20,
+ Sizeof_DeleteSharedIds_is_not_20);
+COMPILE_ASSERT(offsetof(DeleteSharedIds, header) == 0,
+ OffsetOf_DeleteSharedIds_header_not_0);
+COMPILE_ASSERT(offsetof(DeleteSharedIds, namespace_id) == 4,
+ OffsetOf_DeleteSharedIds_namespace_id_not_4);
+COMPILE_ASSERT(offsetof(DeleteSharedIds, n) == 8,
+ OffsetOf_DeleteSharedIds_n_not_8);
+COMPILE_ASSERT(offsetof(DeleteSharedIds, ids_shm_id) == 12,
+ OffsetOf_DeleteSharedIds_ids_shm_id_not_12);
+COMPILE_ASSERT(offsetof(DeleteSharedIds, ids_shm_offset) == 16,
+ OffsetOf_DeleteSharedIds_ids_shm_offset_not_16);
+
+struct RegisterSharedIds {
+ typedef RegisterSharedIds ValueType;
+ static const CommandId kCmdId = kRegisterSharedIds;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+ static uint32 ComputeSize() {
+ return static_cast<uint32>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() {
+ header.SetCmd<ValueType>();
+ }
+
+ void Init(
+ GLuint _namespace_id, GLsizei _n, uint32 _ids_shm_id,
+ uint32 _ids_shm_offset) {
+ SetHeader();
+ namespace_id = _namespace_id;
+ n = _n;
+ ids_shm_id = _ids_shm_id;
+ ids_shm_offset = _ids_shm_offset;
+ }
+
+ void* Set(
+ void* cmd, GLuint _namespace_id, GLsizei _n, uint32 _ids_shm_id,
+ uint32 _ids_shm_offset) {
+ static_cast<ValueType*>(
+ cmd)->Init(_namespace_id, _n, _ids_shm_id, _ids_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32 namespace_id;
+ int32 n;
+ uint32 ids_shm_id;
+ uint32 ids_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(RegisterSharedIds) == 20,
+ Sizeof_RegisterSharedIds_is_not_20);
+COMPILE_ASSERT(offsetof(RegisterSharedIds, header) == 0,
+ OffsetOf_RegisterSharedIds_header_not_0);
+COMPILE_ASSERT(offsetof(RegisterSharedIds, namespace_id) == 4,
+ OffsetOf_RegisterSharedIds_namespace_id_not_4);
+COMPILE_ASSERT(offsetof(RegisterSharedIds, n) == 8,
+ OffsetOf_RegisterSharedIds_n_not_8);
+COMPILE_ASSERT(offsetof(RegisterSharedIds, ids_shm_id) == 12,
+ OffsetOf_RegisterSharedIds_ids_shm_id_not_12);
+COMPILE_ASSERT(offsetof(RegisterSharedIds, ids_shm_offset) == 16,
+ OffsetOf_RegisterSharedIds_ids_shm_offset_not_16);
+
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index d498249..4e003eb 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3270,5 +3270,64 @@ TEST(GLES2FormatTest, GetMaxValueInBuffer) {
EXPECT_EQ(static_cast<uint32>(16), cmd.result_shm_offset);
}
+TEST(GLES2FormatTest, GenSharedIds) {
+ GenSharedIds cmd = { { 0 } };
+ void* next_cmd = cmd.Set(
+ &cmd,
+ static_cast<GLuint>(11),
+ static_cast<GLuint>(12),
+ static_cast<GLsizei>(13),
+ static_cast<uint32>(14),
+ static_cast<uint32>(15));
+ EXPECT_EQ(static_cast<uint32>(GenSharedIds::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<char*>(next_cmd),
+ reinterpret_cast<char*>(&cmd) + sizeof(cmd));
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.namespace_id);
+ EXPECT_EQ(static_cast<GLuint>(12), cmd.id_offset);
+ EXPECT_EQ(static_cast<GLsizei>(13), cmd.n);
+ EXPECT_EQ(static_cast<uint32>(14), cmd.ids_shm_id);
+ EXPECT_EQ(static_cast<uint32>(15), cmd.ids_shm_offset);
+}
+
+TEST(GLES2FormatTest, DeleteSharedIds) {
+ DeleteSharedIds cmd = { { 0 } };
+ void* next_cmd = cmd.Set(
+ &cmd,
+ static_cast<GLuint>(11),
+ static_cast<GLsizei>(12),
+ static_cast<uint32>(13),
+ static_cast<uint32>(14));
+ EXPECT_EQ(static_cast<uint32>(DeleteSharedIds::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<char*>(next_cmd),
+ reinterpret_cast<char*>(&cmd) + sizeof(cmd));
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.namespace_id);
+ EXPECT_EQ(static_cast<GLsizei>(12), cmd.n);
+ EXPECT_EQ(static_cast<uint32>(13), cmd.ids_shm_id);
+ EXPECT_EQ(static_cast<uint32>(14), cmd.ids_shm_offset);
+}
+
+TEST(GLES2FormatTest, RegisterSharedIds) {
+ RegisterSharedIds cmd = { { 0 } };
+ void* next_cmd = cmd.Set(
+ &cmd,
+ static_cast<GLuint>(11),
+ static_cast<GLsizei>(12),
+ static_cast<uint32>(13),
+ static_cast<uint32>(14));
+ EXPECT_EQ(static_cast<uint32>(RegisterSharedIds::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<char*>(next_cmd),
+ reinterpret_cast<char*>(&cmd) + sizeof(cmd));
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.namespace_id);
+ EXPECT_EQ(static_cast<GLsizei>(12), cmd.n);
+ EXPECT_EQ(static_cast<uint32>(13), cmd.ids_shm_id);
+ EXPECT_EQ(static_cast<uint32>(14), cmd.ids_shm_offset);
+}
+
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h
index 7092c1e..ba87b28 100644
--- a/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h
@@ -377,6 +377,12 @@ TEST(GLES2CommandIdTest, CommandIdsMatch) {
GLES2_SwapBuffers_kCmdId_mismatch);
COMPILE_ASSERT(GetMaxValueInBuffer::kCmdId == 438,
GLES2_GetMaxValueInBuffer_kCmdId_mismatch);
+ COMPILE_ASSERT(GenSharedIds::kCmdId == 439,
+ GLES2_GenSharedIds_kCmdId_mismatch);
+ COMPILE_ASSERT(DeleteSharedIds::kCmdId == 440,
+ GLES2_DeleteSharedIds_kCmdId_mismatch);
+ COMPILE_ASSERT(RegisterSharedIds::kCmdId == 441,
+ GLES2_RegisterSharedIds_kCmdId_mismatch);
}
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_ID_TEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 4ce2215..eebe3ff 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -191,6 +191,9 @@
OP(ShaderBinary) /* 436 */ \
OP(ReleaseShaderCompiler) /* 437 */ \
OP(GetMaxValueInBuffer) /* 438 */ \
+ OP(GenSharedIds) /* 439 */ \
+ OP(DeleteSharedIds) /* 440 */ \
+ OP(RegisterSharedIds) /* 441 */ \
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/client/id_allocator.cc b/gpu/command_buffer/common/id_allocator.cc
index 2d244d0..22c55e3 100644
--- a/gpu/command_buffer/client/id_allocator.cc
+++ b/gpu/command_buffer/common/id_allocator.cc
@@ -4,7 +4,7 @@
// This file contains the implementation of IdAllocator.
-#include "../client/id_allocator.h"
+#include "../common/id_allocator.h"
#include "../common/logging.h"
namespace gpu {
@@ -12,7 +12,7 @@ namespace gpu {
IdAllocator::IdAllocator() {
}
-unsigned int IdAllocator::FindFirstFree() const {
+ResourceId IdAllocator::FindFirstFree() const {
ResourceId id = 1;
for (ResourceIdSet::const_iterator it = used_ids_.begin();
it != used_ids_.end(); ++it) {
@@ -24,4 +24,12 @@ unsigned int IdAllocator::FindFirstFree() const {
return id;
}
+ResourceId IdAllocator::AllocateIDAtOrAbove(ResourceId desired_id) {
+ DCHECK_LT(static_cast<ResourceId>(used_ids_.size()),
+ static_cast<ResourceId>(-1));
+ for (; InUse(desired_id); ++desired_id);
+ MarkAsUsed(desired_id);
+ return desired_id;
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/client/id_allocator.h b/gpu/command_buffer/common/id_allocator.h
index 615f020..76edc34 100644
--- a/gpu/command_buffer/client/id_allocator.h
+++ b/gpu/command_buffer/common/id_allocator.h
@@ -30,6 +30,10 @@ class IdAllocator {
return id;
}
+ // Allocates an Id starting at or above desired_id.
+ // Note: may wrap if it starts near limit.
+ ResourceId AllocateIDAtOrAbove(ResourceId desired_id);
+
// Marks an id as used. Returns false if id was already used.
bool MarkAsUsed(ResourceId id) {
std::pair<ResourceIdSet::iterator, bool> result = used_ids_.insert(id);
@@ -43,11 +47,11 @@ class IdAllocator {
// Checks whether or not a resource ID is in use.
bool InUse(ResourceId id) const {
- return used_ids_.find(id) != used_ids_.end();
+ return id == kInvalidResource || used_ids_.find(id) != used_ids_.end();
}
private:
- // TODO(gman): This would work much better with ranges.
+ // TODO(gman): This would work much better with ranges or a hash table.
typedef std::set<ResourceId> ResourceIdSet;
ResourceId FindFirstFree() const;
diff --git a/gpu/command_buffer/client/id_allocator_test.cc b/gpu/command_buffer/common/id_allocator_test.cc
index eafadd7..6869f33 100644
--- a/gpu/command_buffer/client/id_allocator_test.cc
+++ b/gpu/command_buffer/common/id_allocator_test.cc
@@ -4,7 +4,7 @@
// This file has the unit tests for the IdAllocator class.
-#include "gpu/command_buffer/client/id_allocator.h"
+#include "gpu/command_buffer/common/id_allocator.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gpu {
@@ -66,7 +66,7 @@ TEST_F(IdAllocatorTest, TestAdvanced) {
EXPECT_EQ(id1, id2);
}
-// Check that we can choose our own ids and they won't be reused.
+// Checks that we can choose our own ids and they won't be reused.
TEST_F(IdAllocatorTest, MarkAsUsed) {
IdAllocator* allocator = id_allocator();
ResourceId id = allocator->AllocateID();
@@ -83,4 +83,16 @@ TEST_F(IdAllocatorTest, MarkAsUsed) {
EXPECT_EQ(id3, id2 + 2);
}
+// Checks AllocateIdAtOrAbove.
+TEST_F(IdAllocatorTest, AllocateIdAtOrAbove) {
+ const ResourceId kOffset = 123456;
+ IdAllocator* allocator = id_allocator();
+ ResourceId id1 = allocator->AllocateIDAtOrAbove(kOffset);
+ EXPECT_EQ(kOffset, id1);
+ ResourceId id2 = allocator->AllocateIDAtOrAbove(kOffset);
+ EXPECT_GT(id2, kOffset);
+ ResourceId id3 = allocator->AllocateIDAtOrAbove(kOffset);
+ EXPECT_GT(id3, kOffset);
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/docs/gles2_cmd_format_docs.txt b/gpu/command_buffer/docs/gles2_cmd_format_docs.txt
index d1f7326..73882c4 100644
--- a/gpu/command_buffer/docs/gles2_cmd_format_docs.txt
+++ b/gpu/command_buffer/docs/gles2_cmd_format_docs.txt
@@ -2179,4 +2179,39 @@ struct GetMaxValueInBuffer {
uint32 result_shm_offset; //!< uint32
};
+//! Command that generates shared ids for contexts that share resources.
+struct GenSharedIds {
+ static const CommandId kCmdId = 439;
+
+ CommandHeader header;
+ uint32 namespace_id; //!< GLuint
+ uint32 id_offset; //!< GLuint
+ int32 n; //!< GLsizei
+ uint32 ids_shm_id; //!< uint32
+ uint32 ids_shm_offset; //!< uint32
+};
+
+//! Command that deletes shared ids.
+struct DeleteSharedIds {
+ static const CommandId kCmdId = 440;
+
+ CommandHeader header;
+ uint32 namespace_id; //!< GLuint
+ int32 n; //!< GLsizei
+ uint32 ids_shm_id; //!< uint32
+ uint32 ids_shm_offset; //!< uint32
+};
+
+//! Command that registers shared ids. It is an error to attempt
+//! to register an id that is already registered.
+struct RegisterSharedIds {
+ static const CommandId kCmdId = 441;
+
+ CommandHeader header;
+ uint32 namespace_id; //!< GLuint
+ int32 n; //!< GLsizei
+ uint32 ids_shm_id; //!< uint32
+ uint32 ids_shm_offset; //!< uint32
+};
+
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 6e85e30..7a62c72 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "gpu/command_buffer/service/context_group.h"
+#include "gpu/command_buffer/common/id_allocator.h"
#include "gpu/command_buffer/service/buffer_manager.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/program_manager.h"
@@ -55,6 +56,16 @@ bool ContextGroup::Initialize() {
return true;
}
+IdAllocator* ContextGroup::GetIdAllocator(unsigned namespace_id) {
+ IdAllocatorMap::iterator it = id_namespaces_.find(namespace_id);
+ if (it != id_namespaces_.end()) {
+ return it->second.get();
+ }
+ IdAllocator* id_allocator = new IdAllocator();
+ id_namespaces_[namespace_id] = linked_ptr<IdAllocator>(id_allocator);
+ return id_allocator;
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h
index 8ccbb62..2b0bf46 100644
--- a/gpu/command_buffer/service/context_group.h
+++ b/gpu/command_buffer/service/context_group.h
@@ -5,11 +5,15 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_CONTEXT_GROUP_H_
#define GPU_COMMAND_BUFFER_SERVICE_CONTEXT_GROUP_H_
-#include <vector>
+#include <map>
#include "base/basictypes.h"
+#include "base/linked_ptr.h"
#include "base/scoped_ptr.h"
namespace gpu {
+
+class IdAllocator;
+
namespace gles2 {
class GLES2Decoder;
@@ -62,6 +66,8 @@ class ContextGroup {
return shader_manager_.get();
}
+ IdAllocator* GetIdAllocator(unsigned namepsace_id);
+
private:
// Whether or not this context is initialized.
bool initialized_;
@@ -82,6 +88,9 @@ class ContextGroup {
scoped_ptr<ShaderManager> shader_manager_;
+ typedef std::map<uint32, linked_ptr<IdAllocator> > IdAllocatorMap;
+ IdAllocatorMap id_namespaces_;
+
DISALLOW_COPY_AND_ASSIGN(ContextGroup);
};
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 39e9e20..988bc18 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -13,13 +13,13 @@
#include "app/gfx/gl/gl_context.h"
#include "base/callback.h"
-#include "base/linked_ptr.h"
#include "base/scoped_ptr.h"
#include "base/weak_ptr.h"
#include "build/build_config.h"
#define GLES2_GPU_SERVICE 1
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/id_allocator.h"
#include "gpu/command_buffer/service/buffer_manager.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
#include "gpu/command_buffer/service/context_group.h"
@@ -637,6 +637,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Wrapper for glCompileShader.
void DoCompileShader(GLuint shader);
+ // Helper for DeleteSharedIds commands.
+ void DoDeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
+
// Wrapper for glDetachShader
void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
@@ -662,6 +665,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Wrapper for glGenerateMipmap
void DoGenerateMipmap(GLenum target);
+ // Helper for GenSharedIds commands.
+ void DoGenSharedIds(
+ GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
+
// Wrapper for DoGetBooleanv.
void DoGetBooleanv(GLenum pname, GLboolean* params);
@@ -701,6 +708,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Wrapper for glLinkProgram
void DoLinkProgram(GLuint program);
+ // Helper for RegisterSharedIds.
+ void DoRegisterSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
+
// Wrapper for glRenderbufferStorage.
void DoRenderbufferStorage(
GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
@@ -1740,6 +1750,9 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
glGenBuffersARB(1, &service_id);
CreateBufferInfo(client_id, service_id);
info = GetBufferInfo(client_id);
+ IdAllocator* id_allocator =
+ group_->GetIdAllocator(id_namespaces::kBuffers);
+ id_allocator->MarkAsUsed(client_id);
}
}
if (info) {
@@ -1779,6 +1792,9 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
glGenFramebuffersEXT(1, &service_id);
CreateFramebufferInfo(client_id, service_id);
info = GetFramebufferInfo(client_id);
+ IdAllocator* id_allocator =
+ group_->GetIdAllocator(id_namespaces::kFramebuffers);
+ id_allocator->MarkAsUsed(client_id);
} else {
service_id = info->service_id();
}
@@ -1802,6 +1818,10 @@ void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
// It's a new id so make a renderbuffer info for it.
glGenRenderbuffersEXT(1, &service_id);
CreateRenderbufferInfo(client_id, service_id);
+ info = GetRenderbufferInfo(client_id);
+ IdAllocator* id_allocator =
+ group_->GetIdAllocator(id_namespaces::kRenderbuffers);
+ id_allocator->MarkAsUsed(client_id);
} else {
service_id = info->service_id();
}
@@ -1820,6 +1840,9 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
glGenTextures(1, &service_id);
CreateTextureInfo(client_id, service_id);
info = GetTextureInfo(client_id);
+ IdAllocator* id_allocator =
+ group_->GetIdAllocator(id_namespaces::kTextures);
+ id_allocator->MarkAsUsed(client_id);
}
} else {
info = texture_manager()->GetDefaultTextureInfo(target);
@@ -2063,6 +2086,109 @@ error::Error GLES2DecoderImpl::HandleDeleteProgram(
return error::kNoError;
}
+void GLES2DecoderImpl::DoDeleteSharedIds(
+ GLuint namespace_id, GLsizei n, const GLuint* ids) {
+ IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ id_allocator->FreeID(ids[ii]);
+ }
+}
+
+error::Error GLES2DecoderImpl::HandleDeleteSharedIds(
+ uint32 immediate_data_size, const gles2::DeleteSharedIds& c) {
+ GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
+ GLsizei n = static_cast<GLsizei>(c.n);
+ uint32 data_size;
+ if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
+ return error::kOutOfBounds;
+ }
+ const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
+ c.ids_shm_id, c.ids_shm_offset, data_size);
+ if (n < 0) {
+ SetGLError(GL_INVALID_VALUE, "DeleteSharedIds: n < 0");
+ return error::kNoError;
+ }
+ if (ids == NULL) {
+ return error::kOutOfBounds;
+ }
+ DoDeleteSharedIds(namespace_id, n, ids);
+ return error::kNoError;
+}
+
+void GLES2DecoderImpl::DoGenSharedIds(
+ GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
+ IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
+ 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;
+ }
+ }
+}
+
+error::Error GLES2DecoderImpl::HandleGenSharedIds(
+ uint32 immediate_data_size, const gles2::GenSharedIds& c) {
+ GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
+ GLuint id_offset = static_cast<GLuint>(c.id_offset);
+ GLsizei n = static_cast<GLsizei>(c.n);
+ uint32 data_size;
+ if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
+ return error::kOutOfBounds;
+ }
+ GLuint* ids = GetSharedMemoryAs<GLuint*>(
+ c.ids_shm_id, c.ids_shm_offset, data_size);
+ if (n < 0) {
+ SetGLError(GL_INVALID_VALUE, "GenSharedIds: n < 0");
+ return error::kNoError;
+ }
+ if (ids == NULL) {
+ return error::kOutOfBounds;
+ }
+ DoGenSharedIds(namespace_id, id_offset, n, ids);
+ return error::kNoError;
+}
+
+void GLES2DecoderImpl::DoRegisterSharedIds(
+ GLuint namespace_id, GLsizei n, const GLuint* ids) {
+ IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ if (!id_allocator->MarkAsUsed(ids[ii])) {
+ for (GLsizei jj = 0; jj < ii; ++jj) {
+ id_allocator->FreeID(ids[jj]);
+ }
+ SetGLError(
+ GL_INVALID_VALUE,
+ "RegisterSharedIds: attempt to register id that already exists");
+ return;
+ }
+ }
+}
+
+error::Error GLES2DecoderImpl::HandleRegisterSharedIds(
+ uint32 immediate_data_size, const gles2::RegisterSharedIds& c) {
+ GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
+ GLsizei n = static_cast<GLsizei>(c.n);
+ uint32 data_size;
+ if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
+ return error::kOutOfBounds;
+ }
+ GLuint* ids = GetSharedMemoryAs<GLuint*>(
+ c.ids_shm_id, c.ids_shm_offset, data_size);
+ if (n < 0) {
+ SetGLError(GL_INVALID_VALUE, "RegisterSharedIds: n < 0");
+ return error::kNoError;
+ }
+ if (ids == NULL) {
+ return error::kOutOfBounds;
+ }
+ DoRegisterSharedIds(namespace_id, n, ids);
+ return error::kNoError;
+}
+
void GLES2DecoderImpl::DoDrawArrays(
GLenum mode, GLint first, GLsizei count) {
if (IsDrawValid(first + count - 1)) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 1e9a9d0..759e54c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -5,6 +5,7 @@
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/id_allocator.h"
#include "gpu/command_buffer/service/gl_mock.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
@@ -1954,6 +1955,123 @@ TEST_F(GLES2DecoderWithShaderTest, GetMaxValueInBuffer) {
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
+TEST_F(GLES2DecoderTest, SharedIds) {
+ GenSharedIds gen_cmd;
+ RegisterSharedIds reg_cmd;
+ DeleteSharedIds del_cmd;
+
+ const GLuint kNamespaceId = id_namespaces::kTextures;
+ const GLuint kExpectedId1 = 1;
+ const GLuint kExpectedId2 = 2;
+ const GLuint kExpectedId3 = 4;
+ const GLuint kRegisterId = 3;
+ GLuint* ids = GetSharedMemoryAs<GLuint*>();
+ gen_cmd.Init(kNamespaceId, 0, 2, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ IdAllocator* id_allocator = GetIdAllocator(kNamespaceId);
+ ASSERT_TRUE(id_allocator != NULL);
+ // This check is implementation dependant but it's kind of hard to check
+ // otherwise.
+ EXPECT_EQ(kExpectedId1, ids[0]);
+ EXPECT_EQ(kExpectedId2, ids[1]);
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId1));
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId2));
+ EXPECT_FALSE(id_allocator->InUse(kRegisterId));
+ EXPECT_FALSE(id_allocator->InUse(kExpectedId3));
+
+ ClearSharedMemory();
+ ids[0] = kRegisterId;
+ reg_cmd.Init(kNamespaceId, 1, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(reg_cmd));
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId1));
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId2));
+ EXPECT_TRUE(id_allocator->InUse(kRegisterId));
+ EXPECT_FALSE(id_allocator->InUse(kExpectedId3));
+
+ ClearSharedMemory();
+ gen_cmd.Init(kNamespaceId, 0, 1, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(kExpectedId3, ids[0]);
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId1));
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId2));
+ EXPECT_TRUE(id_allocator->InUse(kRegisterId));
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId3));
+
+ ClearSharedMemory();
+ ids[0] = kExpectedId1;
+ ids[1] = kRegisterId;
+ del_cmd.Init(kNamespaceId, 2, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(del_cmd));
+ EXPECT_FALSE(id_allocator->InUse(kExpectedId1));
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId2));
+ EXPECT_FALSE(id_allocator->InUse(kRegisterId));
+ EXPECT_TRUE(id_allocator->InUse(kExpectedId3));
+
+ ClearSharedMemory();
+ ids[0] = kExpectedId3;
+ ids[1] = kExpectedId2;
+ del_cmd.Init(kNamespaceId, 2, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(del_cmd));
+ EXPECT_FALSE(id_allocator->InUse(kExpectedId1));
+ EXPECT_FALSE(id_allocator->InUse(kExpectedId2));
+ EXPECT_FALSE(id_allocator->InUse(kRegisterId));
+ EXPECT_FALSE(id_allocator->InUse(kExpectedId3));
+
+ // Check passing in an id_offset.
+ ClearSharedMemory();
+ const GLuint kOffset = 0xABCDEF;
+ gen_cmd.Init(kNamespaceId, kOffset, 2, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
+ EXPECT_EQ(kOffset, ids[0]);
+ EXPECT_EQ(kOffset + 1, ids[1]);
+}
+
+TEST_F(GLES2DecoderTest, GenSharedIdsBadArgs) {
+ const GLuint kNamespaceId = id_namespaces::kTextures;
+ GenSharedIds cmd;
+ cmd.Init(kNamespaceId, 0, -1, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(kNamespaceId, 0, 1, kInvalidSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(kNamespaceId, 0, 1, kSharedMemoryId, kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_F(GLES2DecoderTest, RegisterSharedIdsBadArgs) {
+ const GLuint kNamespaceId = id_namespaces::kTextures;
+ RegisterSharedIds cmd;
+ cmd.Init(kNamespaceId, -1, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(kNamespaceId, 1, kInvalidSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(kNamespaceId, 1, kSharedMemoryId, kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_F(GLES2DecoderTest, RegisterSharedIdsDuplicateIds) {
+ const GLuint kNamespaceId = id_namespaces::kTextures;
+ const GLuint kRegisterId = 3;
+ RegisterSharedIds cmd;
+ GLuint* ids = GetSharedMemoryAs<GLuint*>();
+ ids[0] = kRegisterId;
+ cmd.Init(kNamespaceId, 1, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(kNamespaceId, 1, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_F(GLES2DecoderTest, DeleteSharedIdsBadArgs) {
+ const GLuint kNamespaceId = id_namespaces::kTextures;
+ DeleteSharedIds cmd;
+ cmd.Init(kNamespaceId, -1, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(kNamespaceId, 1, kInvalidSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(kNamespaceId, 1, kSharedMemoryId, kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
// TODO(gman): BufferData
// TODO(gman): BufferDataImmediate
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
index dbad983..ede9af9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
@@ -550,8 +550,15 @@ TEST_F(GLES2DecoderTest1, DeleteFramebuffersImmediateInvalidArgs) {
EXPECT_EQ(error::kNoError,
ExecuteImmediateCmd(cmd, sizeof(temp)));
}
-// TODO(gman): DeleteProgram
+TEST_F(GLES2DecoderTest1, DeleteProgramValidArgs) {
+ EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId));
+ SpecializedSetup<DeleteProgram, 0>();
+ DeleteProgram cmd;
+ cmd.Init(client_program_id_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
TEST_F(GLES2DecoderTest1, DeleteRenderbuffersValidArgs) {
EXPECT_CALL(
@@ -601,8 +608,15 @@ TEST_F(GLES2DecoderTest1, DeleteRenderbuffersImmediateInvalidArgs) {
EXPECT_EQ(error::kNoError,
ExecuteImmediateCmd(cmd, sizeof(temp)));
}
-// TODO(gman): DeleteShader
+TEST_F(GLES2DecoderTest1, DeleteShaderValidArgs) {
+ EXPECT_CALL(*gl_, DeleteShader(kServiceShaderId));
+ SpecializedSetup<DeleteShader, 0>();
+ DeleteShader cmd;
+ cmd.Init(client_shader_id_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
TEST_F(GLES2DecoderTest1, DeleteTexturesValidArgs) {
EXPECT_CALL(
@@ -1805,5 +1819,7 @@ TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_1) {
// TODO(gman): GetUniformiv
+// TODO(gman): GetUniformLocation
+
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
index ae27310..6bc3097 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -8,8 +8,6 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
-// TODO(gman): GetUniformLocation
-
// TODO(gman): GetUniformLocationImmediate
// TODO(gman): GetUniformLocationBucket
@@ -1622,5 +1620,11 @@ TEST_F(GLES2DecoderTest2, ViewportInvalidArgs3_0) {
}
// TODO(gman): SwapBuffers
// TODO(gman): GetMaxValueInBuffer
+// TODO(gman): GenSharedIds
+
+// TODO(gman): DeleteSharedIds
+
+// TODO(gman): RegisterSharedIds
+
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index bff12c1..8920f31 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -125,6 +125,10 @@ class GLES2DecoderTestBase : public testing::Test {
return reinterpret_cast<T>(ptr);
}
+ IdAllocator* GetIdAllocator(GLuint namespace_id) {
+ return group_.GetIdAllocator(namespace_id);
+ }
+
BufferManager::BufferInfo* GetBufferInfo(GLuint service_id) {
return group_.buffer_manager()->GetBufferInfo(service_id);
}
diff --git a/gpu/demos/framework/window.cc b/gpu/demos/framework/window.cc
index 5e3a309..fce2a08 100644
--- a/gpu/demos/framework/window.cc
+++ b/gpu/demos/framework/window.cc
@@ -84,7 +84,8 @@ bool Window::CreateRenderContext(gfx::PluginWindowHandle hwnd) {
::gles2::SetGLContext(new GLES2Implementation(helper,
transfer_buffer.size,
transfer_buffer.ptr,
- transfer_buffer_id));
+ transfer_buffer_id,
+ false));
return command_buffer.release() != NULL;
}
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 64490bf..dc2c87b 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -155,6 +155,8 @@
'command_buffer/common/gles2_cmd_format.h',
'command_buffer/common/gles2_cmd_utils.cc',
'command_buffer/common/gles2_cmd_utils.h',
+ 'command_buffer/common/id_allocator.cc',
+ 'command_buffer/common/id_allocator.h',
'command_buffer/common/logging.h',
'command_buffer/common/mocks.h',
'command_buffer/common/thread_local.h',
@@ -231,8 +233,6 @@
'command_buffer/client/cmd_buffer_helper.h',
'command_buffer/client/fenced_allocator.cc',
'command_buffer/client/fenced_allocator.h',
- 'command_buffer/client/id_allocator.cc',
- 'command_buffer/client/id_allocator.h',
'command_buffer/client/ring_buffer.cc',
'command_buffer/client/ring_buffer.h',
],
@@ -341,7 +341,6 @@
'command_buffer/client/cmd_buffer_helper_test.cc',
'command_buffer/client/fenced_allocator_test.cc',
'command_buffer/client/gles2_implementation_unittest.cc',
- 'command_buffer/client/id_allocator_test.cc',
'command_buffer/client/ring_buffer_test.cc',
'command_buffer/common/bitfield_helpers_test.cc',
'command_buffer/common/gles2_cmd_format_test.cc',
@@ -356,6 +355,7 @@
'command_buffer/common/gles2_cmd_format_test_autogen.h',
'command_buffer/common/gles2_cmd_id_test.cc',
'command_buffer/common/gles2_cmd_id_test_autogen.h',
+ 'command_buffer/common/id_allocator_test.cc',
'command_buffer/service/buffer_manager_unittest.cc',
'command_buffer/service/context_group_unittest.cc',
'command_buffer/service/cmd_parser_test.cc',
diff --git a/gpu/pgl/pgl.cc b/gpu/pgl/pgl.cc
index 3e42854..b373478 100644
--- a/gpu/pgl/pgl.cc
+++ b/gpu/pgl/pgl.cc
@@ -84,7 +84,8 @@ PGLBoolean PGLContextImpl::Initialize(int32 transfer_buffer_size) {
gles2_helper_,
transfer_buffer.size,
transfer_buffer.ptr,
- transfer_buffer_id_);
+ transfer_buffer_id_,
+ false);
return PGL_TRUE;
}
}