summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-13 23:16:14 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-13 23:16:14 +0000
commit660858bc6459d313b4751e5ba351f9e9ea1739af (patch)
treeb98be5cb0e4ff51caabc2899343e4ef245ee0f97 /gpu
parent70738a32a7651d3f65824f3fdd8f2c2cf52d2b99 (diff)
downloadchromium_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-xgpu/command_buffer/build_gles2_cmd_buffer.py7
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc196
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h34
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h47
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc78
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc2
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;
}