diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-13 23:16:14 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-13 23:16:14 +0000 |
commit | 660858bc6459d313b4751e5ba351f9e9ea1739af (patch) | |
tree | b98be5cb0e4ff51caabc2899343e4ef245ee0f97 /gpu | |
parent | 70738a32a7651d3f65824f3fdd8f2c2cf52d2b99 (diff) | |
download | chromium_src-660858bc6459d313b4751e5ba351f9e9ea1739af.zip chromium_src-660858bc6459d313b4751e5ba351f9e9ea1739af.tar.gz chromium_src-660858bc6459d313b4751e5ba351f9e9ea1739af.tar.bz2 |
Cache bindings on client side in command buffer.
TEST=unit tests and ran OpenGL ES 2.0 conformance tests
BUG=85969
Review URL: http://codereview.chromium.org/7355027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@92442 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-x | gpu/command_buffer/build_gles2_cmd_buffer.py | 7 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.cc | 196 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.h | 34 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_autogen.h | 47 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 78 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 2 |
6 files changed, 301 insertions, 63 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 2b5876d..e2bf5aa 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1107,12 +1107,12 @@ _FUNCTION_INFO = { 'ActiveTexture': { 'decoder_func': 'DoActiveTexture', 'unit_test': False, + 'impl_func': False, }, 'AttachShader': {'decoder_func': 'DoAttachShader'}, 'BindAttribLocation': {'type': 'GLchar', 'bucket': True, 'needs_size': True}, 'BindBuffer': { 'type': 'Bind', - 'impl_decl': False, 'decoder_func': 'DoBindBuffer', 'gen_func': 'GenBuffersARB', }, @@ -1187,7 +1187,6 @@ _FUNCTION_INFO = { 'DeleteBuffers': { 'type': 'DELn', 'gl_test_func': 'glDeleteBuffersARB', - 'impl_decl': False, }, 'DeleteFramebuffers': { 'type': 'DELn', @@ -2733,7 +2732,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; } - %(lc_type)s_id_handler_->MarkAsUsedForBind(%(id)s); + Bind%(type)sHelper(%(arg_string)s); helper_->%(name)s(%(arg_string)s); } @@ -3196,7 +3195,7 @@ TEST_F(%(test_name)s, %(name)sInvalidArgs) { """ % func.GetOriginalArgs()[1].name) for arg in func.GetOriginalArgs(): arg.WriteClientSideValidationCode(file, func) - code = """ %(resource_type)s_id_handler_->FreeIds(%(args)s); + code = """ %(name)sHelper(%(args)s); helper_->%(name)sImmediate(%(args)s); } diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index c7d550d..1a7eeaa 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -443,6 +443,9 @@ GLES2Implementation::GLES2Implementation( transfer_buffer_id_(transfer_buffer_id), pack_alignment_(4), unpack_alignment_(4), + active_texture_unit_(0), + bound_framebuffer_(0), + bound_renderbuffer_(0), bound_array_buffer_id_(0), bound_element_array_buffer_id_(0), client_side_array_id_(0), @@ -505,6 +508,9 @@ GLES2Implementation::GLES2Implementation( pnames, arraysize(pnames), &gl_state_.max_combined_texture_image_units, sizeof(gl_state_)); + texture_units_.reset( + new TextureUnit[gl_state_.max_combined_texture_image_units]); + #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) buffer_id_handler_->MakeIds( kClientSideArrayId, arraysize(reserved_ids_), &reserved_ids_[0]); @@ -692,6 +698,27 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { case GL_NUM_SHADER_BINARY_FORMATS: *params = gl_state_.num_shader_binary_formats; return true; + case GL_ARRAY_BUFFER_BINDING: + *params = bound_array_buffer_id_; + return true; + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + *params = bound_element_array_buffer_id_; + return true; + 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; + case GL_TEXTURE_BINDING_CUBE_MAP: + *params = texture_units_[active_texture_unit_].bound_texture_cube_map; + return true; + case GL_FRAMEBUFFER_BINDING: + *params = bound_framebuffer_; + return true; + case GL_RENDERBUFFER_BINDING: + *params = bound_renderbuffer_; + return true; default: return false; } @@ -1703,31 +1730,30 @@ void GLES2Implementation::ReadPixels( } } -#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) -bool GLES2Implementation::IsBufferReservedId(GLuint id) { - for (size_t ii = 0; ii < arraysize(reserved_ids_); ++ii) { - if (id == reserved_ids_[ii]) { - return true; - } +void GLES2Implementation::ActiveTexture(GLenum texture) { + GPU_CLIENT_LOG("[" << this << "] glActiveTexture(" + << GLES2Util::GetStringEnum(texture) << ")"); + GLuint texture_index = texture - GL_TEXTURE0; + if (texture_index >= + static_cast<GLuint>(gl_state_.max_combined_texture_image_units)) { + SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range."); + return; } - return false; -} -#else -bool GLES2Implementation::IsBufferReservedId(GLuint) { // NOLINT - return false; + + active_texture_unit_ = texture_index; + helper_->ActiveTexture(texture); } -#endif -void GLES2Implementation::BindBuffer(GLenum target, GLuint buffer) { - GPU_CLIENT_LOG("[" << this << "] glBindBuffer(" - << GLES2Util::GetStringBufferTarget(target) << ", " - << buffer << ")"); - if (IsBufferReservedId(buffer)) { - SetGLError(GL_INVALID_OPERATION, "glBindBuffer: reserved buffer id"); - return; - } - buffer_id_handler_->MarkAsUsedForBind(buffer); -#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) +// NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id +// generates a new resource. On newer versions of OpenGL they don't. The code +// related to binding below will need to change if we switch to the new OpenGL +// model. Specifically it assumes a bind will succeed which is always true in +// the old model but possibly not true in the new model if another context has +// deleted the resource. + +void GLES2Implementation::BindBufferHelper( + GLenum target, GLuint buffer) { + // TODO(gman): See note #1 above. switch (target) { case GL_ARRAY_BUFFER: bound_array_buffer_id_ = buffer; @@ -1738,29 +1764,77 @@ void GLES2Implementation::BindBuffer(GLenum target, GLuint buffer) { default: break; } -#endif - helper_->BindBuffer(target, buffer); + // TODO(gman): There's a bug here. If the target is invalid the ID will not be + // used even though it's marked it as used here. + buffer_id_handler_->MarkAsUsedForBind(buffer); } -void GLES2Implementation::DeleteBuffers(GLsizei n, const GLuint* buffers) { - GPU_CLIENT_LOG("[" << this << "] glDeleteBuffers(" - << n << ", " << static_cast<const void*>(buffers) << ")"); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (GLsizei i = 0; i < n; ++i) { - GPU_CLIENT_LOG(" " << i << ": " << buffers[i]); - } - }); - GPU_CLIENT_DCHECK_CODE_BLOCK({ - for (GLsizei i = 0; i < n; ++i) { - GPU_DCHECK(buffers[i] != 0); +void GLES2Implementation::BindFramebufferHelper( + GLenum target, GLuint framebuffer) { + // TODO(gman): See note #1 above. + switch (target) { + case GL_FRAMEBUFFER: + bound_framebuffer_ = framebuffer; + break; + default: + break; + } + // TODO(gman): There's a bug here. If the target is invalid the ID will not be + // used even though it's marked it as used here. + framebuffer_id_handler_->MarkAsUsedForBind(framebuffer); +} + +void GLES2Implementation::BindRenderbufferHelper( + GLenum target, GLuint renderbuffer) { + // TODO(gman): See note #1 above. + switch (target) { + case GL_RENDERBUFFER: + bound_renderbuffer_ = renderbuffer; + break; + default: + break; + } + // TODO(gman): There's a bug here. If the target is invalid the ID will not be + // used even though it's marked it as used here. + renderbuffer_id_handler_->MarkAsUsedForBind(renderbuffer); +} + +void GLES2Implementation::BindTextureHelper(GLenum target, GLuint texture) { + // TODO(gman): See note #1 above. + TextureUnit& unit = texture_units_[active_texture_unit_]; + switch (target) { + case GL_TEXTURE_2D: + unit.bound_texture_2d = texture; + break; + case GL_TEXTURE_CUBE_MAP: + unit.bound_texture_cube_map = texture; + break; + default: + break; + } + // TODO(gman): There's a bug here. If the target is invalid the ID will not be + // used. even though it's marked it as used here. + texture_id_handler_->MarkAsUsedForBind(texture); +} + +#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) +bool GLES2Implementation::IsBufferReservedId(GLuint id) { + for (size_t ii = 0; ii < arraysize(reserved_ids_); ++ii) { + if (id == reserved_ids_[ii]) { + return true; } - }); - if (n < 0) { - SetGLError(GL_INVALID_VALUE, "glDeleteBuffers: n < 0"); - return; } + return false; +} +#else +bool GLES2Implementation::IsBufferReservedId(GLuint /* id */) { + return false; +} +#endif + +void GLES2Implementation::DeleteBuffersHelper( + GLsizei n, const GLuint* buffers) { buffer_id_handler_->FreeIds(n, buffers); -#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) for (GLsizei ii = 0; ii < n; ++ii) { if (buffers[ii] == bound_array_buffer_id_) { bound_array_buffer_id_ = 0; @@ -1769,12 +1843,42 @@ void GLES2Implementation::DeleteBuffers(GLsizei n, const GLuint* buffers) { bound_element_array_buffer_id_ = 0; } } -#endif - // TODO(gman): compute the number of buffers we can delete in 1 call - // based on the size of command buffer and the limit of argument size - // for comments then loop to delete all the buffers. The same needs to - // happen for GenBuffer, GenTextures, DeleteTextures, etc... - helper_->DeleteBuffersImmediate(n, buffers); +} + +void GLES2Implementation::DeleteFramebuffersHelper( + GLsizei n, const GLuint* framebuffers) { + framebuffer_id_handler_->FreeIds(n, framebuffers); + for (GLsizei ii = 0; ii < n; ++ii) { + if (framebuffers[ii] == bound_framebuffer_) { + bound_framebuffer_ = 0; + } + } +} + +void GLES2Implementation::DeleteRenderbuffersHelper( + GLsizei n, const GLuint* renderbuffers) { + renderbuffer_id_handler_->FreeIds(n, renderbuffers); + for (GLsizei ii = 0; ii < n; ++ii) { + if (renderbuffers[ii] == bound_renderbuffer_) { + bound_renderbuffer_ = 0; + } + } +} + +void GLES2Implementation::DeleteTexturesHelper( + GLsizei n, const GLuint* textures) { + texture_id_handler_->FreeIds(n, textures); + 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_]; + if (textures[ii] == unit.bound_texture_2d) { + unit.bound_texture_2d = 0; + } + if (textures[ii] == unit.bound_texture_cube_map) { + unit.bound_texture_cube_map = 0; + } + } + } } void GLES2Implementation::DisableVertexAttribArray(GLuint index) { diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index ef7f07d..cf555bd 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -170,8 +170,6 @@ class GLES2Implementation { // this file instead of having to edit some template or the code generator. #include "../client/gles2_implementation_autogen.h" - void BindBuffer(GLenum target, GLuint buffer); - void DeleteBuffers(GLsizei n, const GLuint* buffers); void DisableVertexAttribArray(GLuint index); void DrawArrays(GLenum mode, GLint first, GLsizei count); void EnableVertexAttribArray(GLuint index); @@ -295,6 +293,20 @@ class GLES2Implementation { GLsizeiptr size; }; + struct TextureUnit { + TextureUnit() + : bound_texture_2d(0), + bound_texture_cube_map(0) { + } + + // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture + GLuint bound_texture_2d; + + // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with + // glBindTexture + GLuint bound_texture_cube_map; + }; + // Gets the shared memory id for the result buffer. uint32 result_shm_id() const { return transfer_buffer_id_; @@ -351,6 +363,16 @@ class GLES2Implementation { bool IsRenderbufferReservedId(GLuint id) { return false; } bool IsTextureReservedId(GLuint id) { return false; } + void BindBufferHelper(GLenum target, GLuint texture); + void BindFramebufferHelper(GLenum target, GLuint texture); + void BindRenderbufferHelper(GLenum target, GLuint texture); + void BindTextureHelper(GLenum target, GLuint texture); + + void DeleteBuffersHelper(GLsizei n, const GLuint* buffers); + void DeleteFramebuffersHelper(GLsizei n, const GLuint* framebuffers); + void DeleteRenderbuffersHelper(GLsizei n, const GLuint* renderbuffers); + void DeleteTexturesHelper(GLsizei n, const GLuint* textures); + // Helper for GetVertexAttrib bool GetVertexAttribHelper(GLuint index, GLenum pname, uint32* param); @@ -402,6 +424,14 @@ class GLES2Implementation { // unpack alignment as last set by glPixelStorei GLint unpack_alignment_; + scoped_array<TextureUnit> texture_units_; + + // 0 to gl_state_.max_combined_texture_image_units. + GLuint active_texture_unit_; + + GLuint bound_framebuffer_; + GLuint bound_renderbuffer_; + // The currently bound array buffer. GLuint bound_array_buffer_id_; diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 902bbdf..edcb5da 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -11,10 +11,7 @@ #ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ -void ActiveTexture(GLenum texture) { - GPU_CLIENT_LOG("[" << this << "] glActiveTexture(" << GLES2Util::GetStringEnum(texture) << ")"); // NOLINT - helper_->ActiveTexture(texture); -} +void ActiveTexture(GLenum texture); void AttachShader(GLuint program, GLuint shader) { GPU_CLIENT_LOG("[" << this << "] glAttachShader(" << program << ", " << shader << ")"); // NOLINT @@ -23,6 +20,16 @@ void AttachShader(GLuint program, GLuint shader) { void BindAttribLocation(GLuint program, GLuint index, const char* name); +void BindBuffer(GLenum target, GLuint buffer) { + GPU_CLIENT_LOG("[" << this << "] glBindBuffer(" << GLES2Util::GetStringBufferTarget(target) << ", " << buffer << ")"); // NOLINT + if (IsBufferReservedId(buffer)) { + SetGLError(GL_INVALID_OPERATION, "BindBuffer: buffer reserved id"); + return; + } + BindBufferHelper(target, buffer); + helper_->BindBuffer(target, buffer); +} + void BindFramebuffer(GLenum target, GLuint framebuffer) { GPU_CLIENT_LOG("[" << this << "] glBindFramebuffer(" << GLES2Util::GetStringFrameBufferTarget(target) << ", " << framebuffer << ")"); // NOLINT if (IsFramebufferReservedId(framebuffer)) { @@ -30,7 +37,7 @@ void BindFramebuffer(GLenum target, GLuint framebuffer) { GL_INVALID_OPERATION, "BindFramebuffer: framebuffer reserved id"); return; } - framebuffer_id_handler_->MarkAsUsedForBind(framebuffer); + BindFramebufferHelper(target, framebuffer); helper_->BindFramebuffer(target, framebuffer); } @@ -41,7 +48,7 @@ void BindRenderbuffer(GLenum target, GLuint renderbuffer) { GL_INVALID_OPERATION, "BindRenderbuffer: renderbuffer reserved id"); return; } - renderbuffer_id_handler_->MarkAsUsedForBind(renderbuffer); + BindRenderbufferHelper(target, renderbuffer); helper_->BindRenderbuffer(target, renderbuffer); } @@ -51,7 +58,7 @@ void BindTexture(GLenum target, GLuint texture) { SetGLError(GL_INVALID_OPERATION, "BindTexture: texture reserved id"); return; } - texture_id_handler_->MarkAsUsedForBind(texture); + BindTextureHelper(target, texture); helper_->BindTexture(target, texture); } @@ -197,6 +204,26 @@ void CullFace(GLenum mode) { helper_->CullFace(mode); } +void DeleteBuffers(GLsizei n, const GLuint* buffers) { + GPU_CLIENT_LOG("[" << this << "] glDeleteBuffers(" << n << ", " << static_cast<const void*>(buffers) << ")"); // NOLINT + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << buffers[i]); + } + }); + GPU_CLIENT_DCHECK_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_DCHECK(buffers[i] != 0); + } + }); + if (n < 0) { + SetGLError(GL_INVALID_VALUE, "glDeleteBuffers: n < 0"); + return; + } + DeleteBuffersHelper(n, buffers); + helper_->DeleteBuffersImmediate(n, buffers); +} + void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { GPU_CLIENT_LOG("[" << this << "] glDeleteFramebuffers(" << n << ", " << static_cast<const void*>(framebuffers) << ")"); // NOLINT GPU_CLIENT_LOG_CODE_BLOCK({ @@ -213,7 +240,7 @@ void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { SetGLError(GL_INVALID_VALUE, "glDeleteFramebuffers: n < 0"); return; } - framebuffer_id_handler_->FreeIds(n, framebuffers); + DeleteFramebuffersHelper(n, framebuffers); helper_->DeleteFramebuffersImmediate(n, framebuffers); } @@ -240,7 +267,7 @@ void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { SetGLError(GL_INVALID_VALUE, "glDeleteRenderbuffers: n < 0"); return; } - renderbuffer_id_handler_->FreeIds(n, renderbuffers); + DeleteRenderbuffersHelper(n, renderbuffers); helper_->DeleteRenderbuffersImmediate(n, renderbuffers); } @@ -267,7 +294,7 @@ void DeleteTextures(GLsizei n, const GLuint* textures) { SetGLError(GL_INVALID_VALUE, "glDeleteTextures: n < 0"); return; } - texture_id_handler_->FreeIds(n, textures); + DeleteTexturesHelper(n, textures); helper_->DeleteTexturesImmediate(n, textures); } diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 2d69fce..9643b55 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -1232,6 +1232,84 @@ TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMBadArgs) { EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); } +// Test that things are cached +TEST_F(GLES2ImplementationTest, GetIntegerCacheRead) { + struct PNameValue { + GLenum pname; + GLint expected; + }; + const PNameValue pairs[] = { + { GL_ACTIVE_TEXTURE, GL_TEXTURE0, }, + { GL_TEXTURE_BINDING_2D, 0, }, + { GL_TEXTURE_BINDING_CUBE_MAP, 0, }, + { GL_FRAMEBUFFER_BINDING, 0, }, + { GL_RENDERBUFFER_BINDING, 0, }, + { GL_ARRAY_BUFFER_BINDING, 0, }, + { GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, }, + { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kMaxCombinedTextureImageUnits, }, + { GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMaxCubeMapTextureSize, }, + { GL_MAX_FRAGMENT_UNIFORM_VECTORS, kMaxFragmentUniformVectors, }, + { GL_MAX_RENDERBUFFER_SIZE, kMaxRenderbufferSize, }, + { GL_MAX_TEXTURE_IMAGE_UNITS, kMaxTextureImageUnits, }, + { GL_MAX_TEXTURE_SIZE, kMaxTextureSize, }, + { GL_MAX_VARYING_VECTORS, kMaxVaryingVectors, }, + { GL_MAX_VERTEX_ATTRIBS, kMaxVertexAttribs, }, + { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMaxVertexTextureImageUnits, }, + { GL_MAX_VERTEX_UNIFORM_VECTORS, kMaxVertexUniformVectors, }, + { GL_NUM_COMPRESSED_TEXTURE_FORMATS, kNumCompressedTextureFormats, }, + { GL_NUM_SHADER_BINARY_FORMATS, kNumShaderBinaryFormats, }, + }; + 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; + gl_->GetIntegerv(pv.pname, &v); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(pv.expected, v); + } + + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .RetiresOnSaturation(); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); +} + +TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) { + struct PNameValue { + GLenum pname; + GLint expected; + }; + gl_->ActiveTexture(GL_TEXTURE4); + gl_->BindBuffer(GL_ARRAY_BUFFER, 2); + gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 3); + gl_->BindFramebuffer(GL_FRAMEBUFFER, 4); + gl_->BindRenderbuffer(GL_RENDERBUFFER, 5); + gl_->BindTexture(GL_TEXTURE_2D, 6); + gl_->BindTexture(GL_TEXTURE_CUBE_MAP, 7); + + const PNameValue pairs[] = { + { GL_ACTIVE_TEXTURE, GL_TEXTURE4, }, + { GL_ARRAY_BUFFER_BINDING, 2, }, + { GL_ELEMENT_ARRAY_BUFFER_BINDING, 3, }, + { GL_FRAMEBUFFER_BINDING, 4, }, + { GL_RENDERBUFFER_BINDING, 5, }, + { GL_TEXTURE_BINDING_2D, 6, }, + { GL_TEXTURE_BINDING_CUBE_MAP, 7, }, + }; + 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; + gl_->GetIntegerv(pv.pname, &v); + EXPECT_EQ(pv.expected, v); + } + + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .RetiresOnSaturation(); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 618829fb..045dfc3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -2618,7 +2618,7 @@ bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) { void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) { GLuint texture_index = texture_unit - GL_TEXTURE0; - if (texture_index > group_->max_texture_units()) { + if (texture_index >= group_->max_texture_units()) { SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range."); return; } |