diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-16 08:39:35 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-16 08:39:35 +0000 |
commit | bf5a8d13ec2321d56c34a986070476f61f3e5b1c (patch) | |
tree | 0109d0e0b685b97d93eb467192fb84f6317e5319 /gpu | |
parent | 2c9bc58faf9a0d67e64d6c38d94dbafea2f4e07b (diff) | |
download | chromium_src-bf5a8d13ec2321d56c34a986070476f61f3e5b1c.zip chromium_src-bf5a8d13ec2321d56c34a986070476f61f3e5b1c.tar.gz chromium_src-bf5a8d13ec2321d56c34a986070476f61f3e5b1c.tar.bz2 |
Add option to not generate resources on bind in OpenGL ES
This allowes us to more efficiently manage ids. It is
not OpenGL ES 2.0 compatible though it probably fits most OpenGL ES
programs.
Note that we need to turn this off on Pepper and/or probably
provide a way for Pepper to turn on on. I'm not sure of the
path Pepper takes to setup. Assuming it goes through
GraphicsContext3D then changes to webkit will be needed to
get the flag all the way down through IPC to the GPU process.
TEST=unit tests and ran a few pages in a chrome build
BUG=92260
Review URL: http://codereview.chromium.org/7633060
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96904 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-x | gpu/command_buffer/build_gles2_cmd_buffer.py | 9 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_demo.cc | 5 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.cc | 314 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.h | 10 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_autogen.h | 16 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 154 | ||||
-rw-r--r-- | gpu/command_buffer/common/id_allocator.h | 4 | ||||
-rw-r--r-- | gpu/command_buffer/service/context_group.cc | 3 | ||||
-rw-r--r-- | gpu/command_buffer/service/context_group.h | 7 | ||||
-rw-r--r-- | gpu/command_buffer/service/context_group_unittest.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 25 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc | 104 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc | 8 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h | 3 | ||||
-rw-r--r-- | gpu/demos/framework/window.cc | 3 | ||||
-rw-r--r-- | gpu/gles2_conform_support/egl/display.cc | 5 |
16 files changed, 531 insertions, 141 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 2f79519..574897e 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -3089,11 +3089,8 @@ class DeleteHandler(TypeHandler): arg.WriteClientSideValidationCode(file, func) file.Write( " GPU_CLIENT_DCHECK(%s != 0);\n" % func.GetOriginalArgs()[-1].name) - file.Write(" DeleteProgramOrShaderHelper(%s);\n" % - func.GetOriginalArgs()[-1].name) - file.Write(" helper_->%s(%s);\n" % - (func.name, func.MakeCmdArgString(""))) - file.Write(" Flush();\n") + file.Write(" %sHelper(%s);\n" % + (func.original_name, func.GetOriginalArgs()[-1].name)) file.Write("}\n") file.Write("\n") @@ -3222,8 +3219,6 @@ TEST_F(%(test_name)s, %(name)sInvalidArgs) { for arg in func.GetOriginalArgs(): arg.WriteClientSideValidationCode(file, func) code = """ %(name)sHelper(%(args)s); - helper_->%(name)sImmediate(%(args)s); - Flush(); } """ diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc index 974f187..66e9026 100644 --- a/gpu/command_buffer/client/gles2_demo.cc +++ b/gpu/command_buffer/client/gles2_demo.cc @@ -64,7 +64,7 @@ bool GLES2Demo::Setup(void* hwnd, int32 size) { if (!command_buffer->Initialize(size)) return NULL; - gpu::gles2::ContextGroup::Ref group(new gpu::gles2::ContextGroup()); + gpu::gles2::ContextGroup::Ref group(new gpu::gles2::ContextGroup(true)); GpuScheduler* gpu_scheduler = GpuScheduler::Create(command_buffer.get(), NULL, group.get()); @@ -101,7 +101,8 @@ bool GLES2Demo::Setup(void* hwnd, int32 size) { transfer_buffer.size, transfer_buffer.ptr, transfer_buffer_id, - false)); + false, + true)); GLFromCPPInit(); diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index fc4f547..e34e476 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -6,6 +6,8 @@ #include "../client/gles2_implementation.h" +#include <set> +#include <queue> #include <GLES2/gl2ext.h> #include "../client/mapped_memory.h" #include "../client/program_info_manager.h" @@ -51,10 +53,11 @@ class NonSharedIdHandler : public IdHandlerInterface { } // Overridden from IdHandlerInterface. - virtual void FreeIds(GLsizei n, const GLuint* ids) { + 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. @@ -79,8 +82,9 @@ class NonSharedNonReusedIdHandler : public IdHandlerInterface { } // Overridden from IdHandlerInterface. - virtual void FreeIds(GLsizei /* n */, const GLuint* /* ids */) { + virtual bool FreeIds(GLsizei /* n */, const GLuint* /* ids */) { // Ids are never freed. + return true; } // Overridden from IdHandlerInterface. @@ -109,20 +113,109 @@ class SharedIdHandler : public IdHandlerInterface { gles2_->GenSharedIdsCHROMIUM(id_namespace_, id_offset, n, ids); } - virtual void FreeIds(GLsizei n, const GLuint* ids) { + virtual bool FreeIds(GLsizei n, const GLuint* ids) { gles2_->DeleteSharedIdsCHROMIUM(id_namespace_, n, ids); + 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() { } + + virtual void MakeIds(GLuint id_offset, GLsizei n, GLuint* ids) { + for (GLsizei ii = 0; ii < n; ++ii) { + ids[ii] = GetId(id_offset); + } } - virtual bool MarkAsUsedForBind(GLuint) { // NOLINT + 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; + + 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; + } + + bool FreeId(GLuint id) { + ResourceIdSet::iterator it = used_ids_.find(id); + if (it == used_ids_.end()) { + return false; + } + used_ids_.erase(it); + free_ids_.push(id); + return true; + } + 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; } @@ -435,7 +528,8 @@ GLES2Implementation::GLES2Implementation( size_t transfer_buffer_size, void* transfer_buffer, int32 transfer_buffer_id, - bool share_resources) + bool share_resources, + bool bind_generates_resource) : helper_(helper), transfer_buffer_( kStartingOffset, @@ -455,7 +549,8 @@ GLES2Implementation::GLES2Implementation( client_side_element_array_id_(0), error_bits_(0), debug_(false), - sharing_resources_(share_resources) { + sharing_resources_(share_resources), + bind_generates_resource_(bind_generates_resource) { GPU_CLIENT_LOG_CODE_BLOCK({ debug_ = CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUClientLogging); @@ -469,16 +564,29 @@ GLES2Implementation::GLES2Implementation( mapped_memory_.reset(new MappedMemoryManager(helper_)); 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)); + if (!bind_generates_resource) { + buffer_id_handler_.reset( + new StrictSharedIdHandler(this, id_namespaces::kBuffers)); + framebuffer_id_handler_.reset( + new StrictSharedIdHandler(this, id_namespaces::kFramebuffers)); + renderbuffer_id_handler_.reset( + new StrictSharedIdHandler(this, id_namespaces::kRenderbuffers)); + program_and_shader_id_handler_.reset( + new StrictSharedIdHandler(this, id_namespaces::kProgramsAndShaders)); + texture_id_handler_.reset( + new StrictSharedIdHandler(this, id_namespaces::kTextures)); + } else { + 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()); @@ -514,7 +622,6 @@ GLES2Implementation::GLES2Implementation( texture_units_.reset( new TextureUnit[gl_state_.max_combined_texture_image_units]); - program_info_manager_.reset(ProgramInfoManager::Create(sharing_resources_)); #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) @@ -705,26 +812,44 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { *params = gl_state_.num_shader_binary_formats; return true; case GL_ARRAY_BUFFER_BINDING: - *params = bound_array_buffer_id_; - return true; + if (bind_generates_resource_) { + *params = bound_array_buffer_id_; + return true; + } + return false; case GL_ELEMENT_ARRAY_BUFFER_BINDING: - *params = bound_element_array_buffer_id_; - return true; + if (bind_generates_resource_) { + *params = bound_element_array_buffer_id_; + return true; + } + return false; case GL_ACTIVE_TEXTURE: *params = active_texture_unit_ + GL_TEXTURE0; return true; case GL_TEXTURE_BINDING_2D: - *params = texture_units_[active_texture_unit_].bound_texture_2d; - return true; + if (bind_generates_resource_) { + *params = texture_units_[active_texture_unit_].bound_texture_2d; + return true; + } + return false; case GL_TEXTURE_BINDING_CUBE_MAP: - *params = texture_units_[active_texture_unit_].bound_texture_cube_map; - return true; + if (bind_generates_resource_) { + *params = texture_units_[active_texture_unit_].bound_texture_cube_map; + return true; + } + return false; case GL_FRAMEBUFFER_BINDING: - *params = bound_framebuffer_; - return true; + if (bind_generates_resource_) { + *params = bound_framebuffer_; + return true; + } + return false; case GL_RENDERBUFFER_BINDING: - *params = bound_renderbuffer_; - return true; + if (bind_generates_resource_) { + *params = bound_renderbuffer_; + return true; + } + return false; default: return false; } @@ -857,13 +982,21 @@ void GLES2Implementation::GenSharedIdsCHROMIUM( } }); TRACE_EVENT0("gpu", "GLES2::GenSharedIdsCHROMIUM"); - GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(n); - helper_->GenSharedIdsCHROMIUM(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()); + GLsizei max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); + GLsizei max_num_per = max_size / sizeof(ids[0]); + while (n) { + GLsizei num = std::min(n, max_num_per); + GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(num); + helper_->GenSharedIdsCHROMIUM( + namespace_id, id_offset, num, + transfer_buffer_id_, + transfer_buffer_.GetOffset(id_buffer)); + WaitForCmd(); + memcpy(ids, id_buffer, sizeof(*ids) * num); + transfer_buffer_.FreePendingToken(id_buffer, helper_->InsertToken()); + n -= num; + ids += num; + } } void GLES2Implementation::DeleteSharedIdsCHROMIUM( @@ -877,13 +1010,21 @@ void GLES2Implementation::DeleteSharedIdsCHROMIUM( } }); TRACE_EVENT0("gpu", "GLES2::DeleteSharedIdsCHROMIUM"); - GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(n); - memcpy(id_buffer, ids, sizeof(*ids) * n); - helper_->DeleteSharedIdsCHROMIUM(namespace_id, n, - transfer_buffer_id_, - transfer_buffer_.GetOffset(id_buffer)); - WaitForCmd(); - transfer_buffer_.FreePendingToken(id_buffer, helper_->InsertToken()); + GLsizei max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); + GLsizei max_num_per = max_size / sizeof(ids[0]); + while (n) { + GLsizei num = std::min(n, max_num_per); + GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(num); + memcpy(id_buffer, ids, sizeof(*ids) * num); + helper_->DeleteSharedIdsCHROMIUM( + namespace_id, num, + transfer_buffer_id_, + transfer_buffer_.GetOffset(id_buffer)); + WaitForCmd(); + transfer_buffer_.FreePendingToken(id_buffer, helper_->InsertToken()); + n -= num; + ids += num; + } } void GLES2Implementation::RegisterSharedIdsCHROMIUM( @@ -897,13 +1038,21 @@ void GLES2Implementation::RegisterSharedIdsCHROMIUM( } }); TRACE_EVENT0("gpu", "GLES2::RegisterSharedIdsCHROMIUM"); - GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(n); - memcpy(id_buffer, ids, sizeof(*ids) * n); - helper_->RegisterSharedIdsCHROMIUM(namespace_id, n, - transfer_buffer_id_, - transfer_buffer_.GetOffset(id_buffer)); - WaitForCmd(); - transfer_buffer_.FreePendingToken(id_buffer, helper_->InsertToken()); + GLsizei max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); + GLsizei max_num_per = max_size / sizeof(ids[0]); + while (n) { + GLsizei num = std::min(n, max_num_per); + GLint* id_buffer = transfer_buffer_.AllocTyped<GLint>(n); + memcpy(id_buffer, ids, sizeof(*ids) * n); + helper_->RegisterSharedIdsCHROMIUM( + namespace_id, n, + transfer_buffer_id_, + transfer_buffer_.GetOffset(id_buffer)); + WaitForCmd(); + transfer_buffer_.FreePendingToken(id_buffer, helper_->InsertToken()); + n -= num; + ids += num; + } } void GLES2Implementation::BindAttribLocation( @@ -943,10 +1092,30 @@ void GLES2Implementation::GetVertexAttribPointerv( }); } -void GLES2Implementation::DeleteProgramOrShaderHelper( - GLuint program_or_shader) { - program_and_shader_id_handler_->FreeIds(1, &program_or_shader); - program_info_manager_->DeleteInfo(program_or_shader); +bool GLES2Implementation::DeleteProgramHelper(GLuint program) { + if (!program_and_shader_id_handler_->FreeIds(1, &program)) { + SetGLError( + GL_INVALID_VALUE, + "glDeleteProgram: id not created by this context."); + return false; + } + program_info_manager_->DeleteInfo(program); + helper_->DeleteProgram(program); + Flush(); + return true; +} + +bool GLES2Implementation::DeleteShaderHelper(GLuint shader) { + if (!program_and_shader_id_handler_->FreeIds(1, &shader)) { + SetGLError( + GL_INVALID_VALUE, + "glDeleteShader: id not created by this context."); + return false; + } + program_info_manager_->DeleteInfo(shader); + helper_->DeleteShader(shader); + Flush(); + return true; } GLint GLES2Implementation::GetAttribLocationHelper( @@ -1964,7 +2133,12 @@ bool GLES2Implementation::IsBufferReservedId(GLuint /* id */) { void GLES2Implementation::DeleteBuffersHelper( GLsizei n, const GLuint* buffers) { - buffer_id_handler_->FreeIds(n, buffers); + if (!buffer_id_handler_->FreeIds(n, buffers)) { + SetGLError( + GL_INVALID_VALUE, + "glDeleteBuffers: id not created by this context."); + return; + } for (GLsizei ii = 0; ii < n; ++ii) { if (buffers[ii] == bound_array_buffer_id_) { bound_array_buffer_id_ = 0; @@ -1973,31 +2147,52 @@ void GLES2Implementation::DeleteBuffersHelper( bound_element_array_buffer_id_ = 0; } } + helper_->DeleteBuffersImmediate(n, buffers); + Flush(); } void GLES2Implementation::DeleteFramebuffersHelper( GLsizei n, const GLuint* framebuffers) { - framebuffer_id_handler_->FreeIds(n, framebuffers); + if (!framebuffer_id_handler_->FreeIds(n, framebuffers)) { + SetGLError( + GL_INVALID_VALUE, + "glDeleteFramebuffers: id not created by this context."); + return; + } for (GLsizei ii = 0; ii < n; ++ii) { if (framebuffers[ii] == bound_framebuffer_) { bound_framebuffer_ = 0; } } + helper_->DeleteFramebuffersImmediate(n, framebuffers); + Flush(); } void GLES2Implementation::DeleteRenderbuffersHelper( GLsizei n, const GLuint* renderbuffers) { - renderbuffer_id_handler_->FreeIds(n, renderbuffers); + if (!renderbuffer_id_handler_->FreeIds(n, renderbuffers)) { + SetGLError( + GL_INVALID_VALUE, + "glDeleteRenderbuffers: id not created by this context."); + return; + } for (GLsizei ii = 0; ii < n; ++ii) { if (renderbuffers[ii] == bound_renderbuffer_) { bound_renderbuffer_ = 0; } } + helper_->DeleteRenderbuffersImmediate(n, renderbuffers); + Flush(); } void GLES2Implementation::DeleteTexturesHelper( GLsizei n, const GLuint* textures) { - texture_id_handler_->FreeIds(n, textures); + if (!texture_id_handler_->FreeIds(n, textures)) { + SetGLError( + GL_INVALID_VALUE, + "glDeleteTextures: id not created by this context."); + return; + } for (GLsizei ii = 0; ii < n; ++ii) { for (GLint tt = 0; tt < gl_state_.max_combined_texture_image_units; ++tt) { TextureUnit& unit = texture_units_[active_texture_unit_]; @@ -2009,6 +2204,8 @@ void GLES2Implementation::DeleteTexturesHelper( } } } + helper_->DeleteTexturesImmediate(n, textures); + Flush(); } void GLES2Implementation::DisableVertexAttribArray(GLuint index) { @@ -2428,3 +2625,4 @@ void GLES2Implementation::GetProgramInfoCHROMIUM( } // namespace gles2 } // namespace gpu + diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 9ab625c..057b046e 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -87,7 +87,7 @@ class IdHandlerInterface { virtual void MakeIds(GLuint id_offset, GLsizei n, GLuint* ids) = 0; // Frees some ids. - virtual void FreeIds(GLsizei n, const GLuint* ids) = 0; + 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; @@ -156,7 +156,8 @@ class GLES2Implementation { size_t transfer_buffer_size, void* transfer_buffer, int32 transfer_buffer_id, - bool share_resources); + bool share_resources, + bool bind_generates_resource = true); // Will remove in 2 CLs! ~GLES2Implementation(); @@ -177,7 +178,6 @@ class GLES2Implementation { void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params); void GetProgramInfoCHROMIUMHelper(GLuint program, std::vector<int8>* result); - void DeleteProgramOrShaderHelper(GLuint program_or_shader); GLint GetAttribLocationHelper(GLuint program, const char* name); GLint GetUniformLocationHelper(GLuint program, const char* name); bool GetActiveAttribHelper( @@ -383,6 +383,8 @@ class GLES2Implementation { void DeleteFramebuffersHelper(GLsizei n, const GLuint* framebuffers); void DeleteRenderbuffersHelper(GLsizei n, const GLuint* renderbuffers); void DeleteTexturesHelper(GLsizei n, const GLuint* textures); + bool DeleteProgramHelper(GLuint program); + bool DeleteShaderHelper(GLuint shader); // Helper for GetVertexAttrib bool GetVertexAttribHelper(GLuint index, GLenum pname, uint32* param); @@ -474,6 +476,8 @@ class GLES2Implementation { // Whether or not this context is sharing resources. bool sharing_resources_; + bool bind_generates_resource_; + // Map of GLenum to Strings for glGetString. We need to cache these because // the pointer passed back to the client has to remain valid for eternity. typedef std::map<uint32, std::set<std::string> > GLStringMap; diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 702ad02..ba061a5 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -221,8 +221,6 @@ void DeleteBuffers(GLsizei n, const GLuint* buffers) { return; } DeleteBuffersHelper(n, buffers); - helper_->DeleteBuffersImmediate(n, buffers); - Flush(); } void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { @@ -242,16 +240,12 @@ void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { return; } DeleteFramebuffersHelper(n, framebuffers); - helper_->DeleteFramebuffersImmediate(n, framebuffers); - Flush(); } void DeleteProgram(GLuint program) { GPU_CLIENT_LOG("[" << this << "] glDeleteProgram(" << program << ")"); GPU_CLIENT_DCHECK(program != 0); - DeleteProgramOrShaderHelper(program); - helper_->DeleteProgram(program); - Flush(); + DeleteProgramHelper(program); } void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { @@ -271,16 +265,12 @@ void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { return; } DeleteRenderbuffersHelper(n, renderbuffers); - helper_->DeleteRenderbuffersImmediate(n, renderbuffers); - Flush(); } void DeleteShader(GLuint shader) { GPU_CLIENT_LOG("[" << this << "] glDeleteShader(" << shader << ")"); GPU_CLIENT_DCHECK(shader != 0); - DeleteProgramOrShaderHelper(shader); - helper_->DeleteShader(shader); - Flush(); + DeleteShaderHelper(shader); } void DeleteTextures(GLsizei n, const GLuint* textures) { @@ -300,8 +290,6 @@ void DeleteTextures(GLsizei n, const GLuint* textures) { return; } DeleteTexturesHelper(n, textures); - helper_->DeleteTexturesImmediate(n, textures); - Flush(); } void DepthFunc(GLenum func) { diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 68ae339..324d51f 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -130,13 +130,14 @@ const int32 GLES2MockCommandBufferHelper::kTransferBufferId; namespace gles2 { -using testing::Return; -using testing::Mock; -using testing::Truly; -using testing::Sequence; +using testing::_; using testing::DoAll; +using testing::InSequence; using testing::Invoke; -using testing::_; +using testing::Mock; +using testing::Sequence; +using testing::Truly; +using testing::Return; ACTION_P(SetMemory, obj) { memcpy(arg0, &obj, sizeof(obj)); @@ -208,6 +209,7 @@ class GLES2ImplementationTest : public testing::Test { static const GLint kMaxVertexUniformVectors = 128; static const GLint kNumCompressedTextureFormats = 0; static const GLint kNumShaderBinaryFormats = 0; + static const GLuint kStartId = 1024; GLES2ImplementationTest() : commands_(NULL), @@ -216,6 +218,13 @@ class GLES2ImplementationTest : public testing::Test { } virtual void SetUp() { + Initialize(false, true); + } + + virtual void TearDown() { + } + + void Initialize(bool shared_resources, bool bind_generates_resource) { offset_ = GLES2Implementation::kStartingOffset; command_buffer_.reset(new MockGLES2CommandBuffer()); @@ -249,17 +258,48 @@ class GLES2ImplementationTest : public testing::Test { AllocateTransferBuffer(sizeof(state)); // in uint32 offset = AllocateTransferBuffer(sizeof(state)); // out - EXPECT_CALL(*command_buffer_, OnFlush(_)) - .WillOnce(SetMemoryAtOffset(offset, state)) - .RetiresOnSaturation(); - GetNextToken(); // eat the token that starting up will use. - - gl_.reset(new GLES2Implementation( - helper_.get(), - kTransferBufferSize, - transfer_buffer_.ptr, - kTransferBufferId, - false)); + { + InSequence sequence; + + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemoryAtOffset(offset, state)) + .RetiresOnSaturation(); + GetNextToken(); // eat the token that starting up will use. + + // Must match StrictSharedIdHandler::kNumIdsToGet. + GLuint num_ids = 2048; + scoped_array<GLuint> all_ids(new GLuint[num_ids]); + if (shared_resources) { + if (!bind_generates_resource) { + GLuint start = kStartId; + GLuint max_num_per = MaxTransferBufferSize() / sizeof(GLuint); + GLuint* ids = all_ids.get(); + for (GLuint ii = 0; ii < num_ids; ++ii) { + ids[ii] = start + ii; + } + while (num_ids) { + GLuint num = std::min(num_ids, max_num_per); + size_t size = num * sizeof(ids[0]); + uint32 offset = AllocateTransferBuffer(size); + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemoryAtOffsetFromArray(offset, ids, size)) + .RetiresOnSaturation(); + GetNextToken(); + start += num; + ids += num; + num_ids -= num; + } + } + } + + gl_.reset(new GLES2Implementation( + helper_.get(), + kTransferBufferSize, + transfer_buffer_.ptr, + kTransferBufferId, + shared_resources, + bind_generates_resource)); + } EXPECT_CALL(*command_buffer_, OnFlush(_)) .Times(1) @@ -271,9 +311,6 @@ class GLES2ImplementationTest : public testing::Test { ClearCommands(); } - virtual void TearDown() { - } - const void* GetPut() { return helper_->GetSpace(0); } @@ -334,6 +371,13 @@ class GLES2ImplementationTest : public testing::Test { uint32 offset_; }; +class GLES2ImplementationStrictSharedTest : public GLES2ImplementationTest { + protected: + virtual void SetUp() { + Initialize(true, false); + } +}; + // GCC requires these declarations, but MSVC requires they not be present #ifndef _MSC_VER const int32 GLES2ImplementationTest::kTransferBufferId; @@ -1686,6 +1730,78 @@ TEST_F(GLES2ImplementationTest, TexImage2DSubRows) { GetTransferAddressFromOffsetAs<uint8>(offset4, part_size))); } +// Test that GenBuffer does not call GenSharedIds. +// This is because with client side arrays on we know the StrictSharedIdHandler +// for buffers has already gotten a set of ids +TEST_F(GLES2ImplementationStrictSharedTest, GenBuffer) { + // Starts at + 2 because client side arrays take first 2 ids. + GLuint ids[3] = { kStartId + 2, kStartId + 3, kStartId + 4 }; + struct Cmds { + GenBuffersImmediate gen; + GLuint data[3]; + }; + Cmds expected; + expected.gen.Init(arraysize(ids), &ids[0]); + gl_->GenBuffers(arraysize(ids), &ids[0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_NE(0u, ids[0]); + EXPECT_NE(0u, ids[1]); + EXPECT_NE(0u, ids[2]); +} + +// Binds can not be cached with bind_generates_resource = false because +// our id might not be valid. +TEST_F(GLES2ImplementationStrictSharedTest, BindsNotCached) { + struct PNameValue { + GLenum pname; + GLint expected; + }; + const PNameValue pairs[] = { + { GL_TEXTURE_BINDING_2D, 1, }, + { GL_TEXTURE_BINDING_CUBE_MAP, 2, }, + { GL_FRAMEBUFFER_BINDING, 3, }, + { GL_RENDERBUFFER_BINDING, 4, }, + { GL_ARRAY_BUFFER_BINDING, 5, }, + { GL_ELEMENT_ARRAY_BUFFER_BINDING, 6, }, + }; + size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]); + for (size_t ii = 0; ii < num_pairs; ++ii) { + const PNameValue& pv = pairs[ii]; + GLint v = -1; + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(SizedResultHelper<GLuint>(pv.expected))) + .RetiresOnSaturation(); + gl_->GetIntegerv(pv.pname, &v); + EXPECT_EQ(pv.expected, v); + } +} + +TEST_F(GLES2ImplementationStrictSharedTest, CanNotDeleteIdsWeDidNotCreate) { + GLuint id = 0x12345678; + + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .RetiresOnSaturation(); + + gl_->DeleteBuffers(1, &id); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); + gl_->DeleteFramebuffers(1, &id); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); + gl_->DeleteRenderbuffers(1, &id); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); + gl_->DeleteTextures(1, &id); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); + gl_->DeleteProgram(id); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); + gl_->DeleteShader(id); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/common/id_allocator.h b/gpu/command_buffer/common/id_allocator.h index 23c93d2..56220b2 100644 --- a/gpu/command_buffer/common/id_allocator.h +++ b/gpu/command_buffer/common/id_allocator.h @@ -11,10 +11,6 @@ #include <utility> #include "../common/types.h" -// TODO(apatrick): Having regular GL flush semantics on the client side, it -// probably isn't necessary to round trip to the service to allocate IDs. -// Retire this code. - namespace gpu { // A resource ID, key to the resource maps. diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 36c8d03..b93c034 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -16,9 +16,10 @@ namespace gpu { namespace gles2 { -ContextGroup::ContextGroup() +ContextGroup::ContextGroup(bool bind_generates_resource) : initialized_(false), have_context_(true), + bind_generates_resource_(bind_generates_resource), max_vertex_attribs_(0u), max_texture_units_(0u), max_texture_image_units_(0u), diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index a2e6382..f130dc6 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -36,7 +36,7 @@ class ContextGroup : public base::RefCounted<ContextGroup> { public: typedef scoped_refptr<ContextGroup> Ref; - ContextGroup(); + explicit ContextGroup(bool bind_generates_resource); ~ContextGroup(); // This should only be called by GLES2Decoder. @@ -48,6 +48,10 @@ class ContextGroup : public base::RefCounted<ContextGroup> { have_context_ = have_context; } + bool bind_generates_resource() { + return bind_generates_resource_; + } + uint32 max_vertex_attribs() const { return max_vertex_attribs_; } @@ -113,6 +117,7 @@ class ContextGroup : public base::RefCounted<ContextGroup> { // Whether or not this context is initialized. bool initialized_; bool have_context_; + bool bind_generates_resource_; uint32 max_vertex_attribs_; uint32 max_texture_units_; diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc index a651854..c8a78f3 100644 --- a/gpu/command_buffer/service/context_group_unittest.cc +++ b/gpu/command_buffer/service/context_group_unittest.cc @@ -36,7 +36,7 @@ class ContextGroupTest : public testing::Test { virtual void SetUp() { gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); - group_ = ContextGroup::Ref(new ContextGroup()); + group_ = ContextGroup::Ref(new ContextGroup(true)); } virtual void TearDown() { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 7a04a7c..22e01c2 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -2682,6 +2682,12 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) { if (client_id != 0) { info = GetBufferInfo(client_id); if (!info) { + if (!group_->bind_generates_resource()) { + SetGLError(GL_INVALID_VALUE, + "glBindBuffer: id not generated by glGenBuffers"); + return; + } + // It's a new id so make a buffer info for it. glGenBuffersARB(1, &service_id); CreateBufferInfo(client_id, service_id); @@ -2761,6 +2767,12 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) { if (client_id != 0) { info = GetFramebufferInfo(client_id); if (!info) { + if (!group_->bind_generates_resource()) { + SetGLError(GL_INVALID_VALUE, + "glBindFramebuffer: id not generated by glGenFramebuffers"); + return; + } + // It's a new id so make a framebuffer info for it. glGenFramebuffersEXT(1, &service_id); CreateFramebufferInfo(client_id, service_id); @@ -2800,6 +2812,13 @@ void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) { if (client_id != 0) { info = GetRenderbufferInfo(client_id); if (!info) { + if (!group_->bind_generates_resource()) { + SetGLError( + GL_INVALID_VALUE, + "glBindRenderbuffer: id not generated by glGenRenderbuffers"); + return; + } + // It's a new id so make a renderbuffer info for it. glGenRenderbuffersEXT(1, &service_id); CreateRenderbufferInfo(client_id, service_id); @@ -2822,6 +2841,12 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) { if (client_id != 0) { info = GetTextureInfo(client_id); if (!info) { + if (!group_->bind_generates_resource()) { + SetGLError(GL_INVALID_VALUE, + "glBindTexture: id not generated by glGenTextures"); + return; + } + // It's a new id so make a texture info for it. glGenTextures(1, &service_id); CreateTextureInfo(client_id, service_id); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index d619b12..fa85ea5 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -96,7 +96,8 @@ class GLES2DecoderRGBBackbufferTest : public GLES2DecoderWithShaderTest { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource SetupDefaultProgram(); } }; @@ -3190,7 +3191,8 @@ TEST_F(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) { false, // has stencil true, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3220,7 +3222,8 @@ TEST_F(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3250,7 +3253,8 @@ TEST_F(GLES2DecoderManualInitTest, ActualDepthMatchesRequestedDepth) { false, // has stencil false, // request alpha true, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3280,7 +3284,8 @@ TEST_F(GLES2DecoderManualInitTest, ActualDepthDoesNotMatchRequestedDepth) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3310,7 +3315,8 @@ TEST_F(GLES2DecoderManualInitTest, ActualStencilMatchesRequestedStencil) { true, // has stencil false, // request alpha false, // request depth - true); // request stencil + true, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3340,7 +3346,8 @@ TEST_F(GLES2DecoderManualInitTest, ActualStencilDoesNotMatchRequestedStencil) { true, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3370,7 +3377,8 @@ TEST_F(GLES2DecoderManualInitTest, DepthEnableWithDepth) { false, // has stencil false, // request alpha true, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource Enable cmd; cmd.Init(GL_DEPTH_TEST); @@ -3426,7 +3434,8 @@ TEST_F(GLES2DecoderManualInitTest, DepthEnableWithoutRequestedDepth) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource Enable cmd; cmd.Init(GL_DEPTH_TEST); @@ -3482,7 +3491,8 @@ TEST_F(GLES2DecoderManualInitTest, StencilEnableWithStencil) { true, // has stencil false, // request alpha false, // request depth - true); // request stencil + true, // request stencil + true); // bind generates resource Enable cmd; cmd.Init(GL_STENCIL_TEST); @@ -3538,7 +3548,8 @@ TEST_F(GLES2DecoderManualInitTest, StencilEnableWithoutRequestedStencil) { true, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource Enable cmd; cmd.Init(GL_STENCIL_TEST); @@ -3594,7 +3605,8 @@ TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilReportsCorrectValues) { true, // has stencil false, // request alpha true, // request depth - true); // request stencil + true, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3637,7 +3649,8 @@ TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilNoRequestedStencil) { true, // has stencil false, // request alpha true, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3680,7 +3693,8 @@ TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferDepth) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, @@ -3756,7 +3770,8 @@ TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferStencil) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, @@ -4107,7 +4122,8 @@ TEST_F(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleGLError) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); EXPECT_CALL(*gl_, GetError()) @@ -4169,7 +4185,8 @@ TEST_F(GLES2DecoderManualInitTest, GetCompressedTextureFormats) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -4225,7 +4242,8 @@ TEST_F(GLES2DecoderManualInitTest, GetNoCompressedTextureFormats) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -4296,7 +4314,8 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalBindTexture) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, kNewServiceId)); EXPECT_CALL(*gl_, GenTextures(1, _)) .WillOnce(SetArgumentPointee<1>(kNewServiceId)); @@ -4317,7 +4336,8 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalGetBinding) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); EXPECT_CALL(*gl_, GetError()) @@ -4349,7 +4369,8 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureDefaults) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id_); @@ -4368,7 +4389,8 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureParam) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); @@ -4425,7 +4447,8 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureParamInvalid) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); @@ -4464,7 +4487,8 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTexImage2DError) { false, // has stencil false, // request alpha false, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource GLenum target = GL_TEXTURE_EXTERNAL_OES; GLint level = 0; @@ -4485,6 +4509,38 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTexImage2DError) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } +TEST_F(GLES2DecoderManualInitTest, BindGeneratesResourceFalse) { + InitDecoder( + "", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + false); // bind generates resource + + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, kInvalidClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + BindBuffer cmd2; + cmd2.Init(GL_ARRAY_BUFFER, kInvalidClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + BindFramebuffer cmd3; + cmd3.Init(GL_FRAMEBUFFER, kInvalidClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd3)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + BindRenderbuffer cmd4; + cmd4.Init(GL_RENDERBUFFER, kInvalidClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd4)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + // TODO(gman): Complete this test. // TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) { // } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index d80576d..41e42ad0 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -55,7 +55,8 @@ void GLES2DecoderTestBase::SetUp() { false, // has stencil true, // request alpha true, // request depth - false); // request stencil + false, // request stencil + true); // bind generates resource } void GLES2DecoderTestBase::InitDecoder( @@ -65,11 +66,12 @@ void GLES2DecoderTestBase::InitDecoder( bool has_stencil, bool request_alpha, bool request_depth, - bool request_stencil) { + bool request_stencil, + bool bind_generates_resource) { gl_.reset(new StrictMock<MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); surface_manager_.reset(new StrictMock<MockSurfaceManager>); - group_ = ContextGroup::Ref(new ContextGroup()); + group_ = ContextGroup::Ref(new ContextGroup(bind_generates_resource)); InSequence sequence; 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 22d341a..be2ba02 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -168,7 +168,8 @@ class GLES2DecoderTestBase : public testing::Test { bool has_stencil, bool request_alpha, bool request_depth, - bool request_stencil); + bool request_stencil, + bool bind_generates_resource); const ContextGroup& group() const { return *group_.get(); diff --git a/gpu/demos/framework/window.cc b/gpu/demos/framework/window.cc index 34f20fd..e5d24dd 100644 --- a/gpu/demos/framework/window.cc +++ b/gpu/demos/framework/window.cc @@ -90,7 +90,8 @@ bool Window::CreateRenderContext(gfx::PluginWindowHandle hwnd) { transfer_buffer.size, transfer_buffer.ptr, transfer_buffer_id, - false)); + false, + true)); return command_buffer.release() != NULL; } diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index 05603a0..7b5d26b 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -108,7 +108,7 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, using gpu::GpuScheduler; std::vector<int32> attribs; - gpu::gles2::ContextGroup::Ref group(new gpu::gles2::ContextGroup()); + gpu::gles2::ContextGroup::Ref group(new gpu::gles2::ContextGroup(true)); scoped_ptr<GpuScheduler> gpu_scheduler( GpuScheduler::Create(command_buffer_.get(), NULL, @@ -160,7 +160,8 @@ EGLContext Display::CreateContext(EGLConfig config, buffer.size, buffer.ptr, transfer_buffer_id_, - share_resources)); + share_resources, + true)); context_->EnableFeatureCHROMIUM( "pepper3d_allow_buffers_on_multiple_targets"); |