// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "gpu/command_buffer/service/test_helper.h" #include #include #include "base/strings/string_number_conversions.h" #include "base/strings/string_tokenizer.h" #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" using ::testing::_; using ::testing::DoAll; using ::testing::InSequence; using ::testing::MatcherCast; using ::testing::Pointee; using ::testing::Return; using ::testing::SetArrayArgument; using ::testing::SetArgumentPointee; using ::testing::StrEq; using ::testing::StrictMock; namespace gpu { namespace gles2 { // GCC requires these declarations, but MSVC requires they not be present #ifndef COMPILER_MSVC const GLuint TestHelper::kServiceBlackTexture2dId; const GLuint TestHelper::kServiceDefaultTexture2dId; const GLuint TestHelper::kServiceBlackTextureCubemapId; const GLuint TestHelper::kServiceDefaultTextureCubemapId; const GLuint TestHelper::kServiceBlackExternalTextureId; const GLuint TestHelper::kServiceDefaultExternalTextureId; const GLuint TestHelper::kServiceBlackRectangleTextureId; const GLuint TestHelper::kServiceDefaultRectangleTextureId; const GLint TestHelper::kMaxSamples; const GLint TestHelper::kMaxRenderbufferSize; const GLint TestHelper::kMaxTextureSize; const GLint TestHelper::kMaxCubeMapTextureSize; const GLint TestHelper::kNumVertexAttribs; const GLint TestHelper::kNumTextureUnits; const GLint TestHelper::kMaxTextureImageUnits; const GLint TestHelper::kMaxVertexTextureImageUnits; const GLint TestHelper::kMaxFragmentUniformVectors; const GLint TestHelper::kMaxFragmentUniformComponents; const GLint TestHelper::kMaxVaryingVectors; const GLint TestHelper::kMaxVaryingFloats; const GLint TestHelper::kMaxVertexUniformVectors; const GLint TestHelper::kMaxVertexUniformComponents; #endif void TestHelper::SetupTextureInitializationExpectations( ::gfx::MockGLInterface* gl, GLenum target, bool use_default_textures) { InSequence sequence; bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); static GLuint texture_2d_ids[] = { kServiceBlackTexture2dId, kServiceDefaultTexture2dId }; static GLuint texture_cube_map_ids[] = { kServiceBlackTextureCubemapId, kServiceDefaultTextureCubemapId }; static GLuint texture_external_oes_ids[] = { kServiceBlackExternalTextureId, kServiceDefaultExternalTextureId }; static GLuint texture_rectangle_arb_ids[] = { kServiceBlackRectangleTextureId, kServiceDefaultRectangleTextureId }; const GLuint* texture_ids = NULL; switch (target) { case GL_TEXTURE_2D: texture_ids = &texture_2d_ids[0]; break; case GL_TEXTURE_CUBE_MAP: texture_ids = &texture_cube_map_ids[0]; break; case GL_TEXTURE_EXTERNAL_OES: texture_ids = &texture_external_oes_ids[0]; break; case GL_TEXTURE_RECTANGLE_ARB: texture_ids = &texture_rectangle_arb_ids[0]; break; default: NOTREACHED(); } int array_size = use_default_textures ? 2 : 1; EXPECT_CALL(*gl, GenTextures(array_size, _)) .WillOnce(SetArrayArgument<1>(texture_ids, texture_ids + array_size)) .RetiresOnSaturation(); for (int ii = 0; ii < array_size; ++ii) { EXPECT_CALL(*gl, BindTexture(target, texture_ids[ii])) .Times(1) .RetiresOnSaturation(); if (needs_initialization) { if (needs_faces) { static GLenum faces[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, }; for (size_t ii = 0; ii < arraysize(faces); ++ii) { EXPECT_CALL(*gl, TexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, _)) .Times(1) .RetiresOnSaturation(); } } else { EXPECT_CALL(*gl, TexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, _)) .Times(1) .RetiresOnSaturation(); } } } EXPECT_CALL(*gl, BindTexture(target, 0)) .Times(1) .RetiresOnSaturation(); } void TestHelper::SetupTextureManagerInitExpectations( ::gfx::MockGLInterface* gl, const char* extensions, bool use_default_textures) { InSequence sequence; SetupTextureInitializationExpectations( gl, GL_TEXTURE_2D, use_default_textures); SetupTextureInitializationExpectations( gl, GL_TEXTURE_CUBE_MAP, use_default_textures); bool ext_image_external = false; bool arb_texture_rectangle = false; base::CStringTokenizer t(extensions, extensions + strlen(extensions), " "); while (t.GetNext()) { if (t.token() == "GL_OES_EGL_image_external") { ext_image_external = true; break; } if (t.token() == "GL_ARB_texture_rectangle") { arb_texture_rectangle = true; break; } } if (ext_image_external) { SetupTextureInitializationExpectations( gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures); } if (arb_texture_rectangle) { SetupTextureInitializationExpectations( gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures); } } void TestHelper::SetupTextureDestructionExpectations( ::gfx::MockGLInterface* gl, GLenum target, bool use_default_textures) { if (!use_default_textures) return; GLuint texture_id = 0; switch (target) { case GL_TEXTURE_2D: texture_id = kServiceDefaultTexture2dId; break; case GL_TEXTURE_CUBE_MAP: texture_id = kServiceDefaultTextureCubemapId; break; case GL_TEXTURE_EXTERNAL_OES: texture_id = kServiceDefaultExternalTextureId; break; case GL_TEXTURE_RECTANGLE_ARB: texture_id = kServiceDefaultRectangleTextureId; break; default: NOTREACHED(); } EXPECT_CALL(*gl, DeleteTextures(1, Pointee(texture_id))) .Times(1) .RetiresOnSaturation(); } void TestHelper::SetupTextureManagerDestructionExpectations( ::gfx::MockGLInterface* gl, const char* extensions, bool use_default_textures) { SetupTextureDestructionExpectations(gl, GL_TEXTURE_2D, use_default_textures); SetupTextureDestructionExpectations( gl, GL_TEXTURE_CUBE_MAP, use_default_textures); bool ext_image_external = false; bool arb_texture_rectangle = false; base::CStringTokenizer t(extensions, extensions + strlen(extensions), " "); while (t.GetNext()) { if (t.token() == "GL_OES_EGL_image_external") { ext_image_external = true; break; } if (t.token() == "GL_ARB_texture_rectangle") { arb_texture_rectangle = true; break; } } if (ext_image_external) { SetupTextureDestructionExpectations( gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures); } if (arb_texture_rectangle) { SetupTextureDestructionExpectations( gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures); } EXPECT_CALL(*gl, DeleteTextures(4, _)) .Times(1) .RetiresOnSaturation(); } void TestHelper::SetupContextGroupInitExpectations( ::gfx::MockGLInterface* gl, const DisallowedFeatures& disallowed_features, const char* extensions, const char* gl_version, bool bind_generates_resource) { InSequence sequence; SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", gl_version); std::string l_version(StringToLowerASCII(std::string(gl_version))); bool is_es3 = (l_version.substr(0, 12) == "opengl es 3."); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _)) .WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize)) .RetiresOnSaturation(); if (strstr(extensions, "GL_EXT_framebuffer_multisample") || strstr(extensions, "GL_EXT_multisampled_render_to_texture") || is_es3) { EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _)) .WillOnce(SetArgumentPointee<1>(kMaxSamples)) .RetiresOnSaturation(); } else if (strstr(extensions, "GL_IMG_multisampled_render_to_texture")) { EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES_IMG, _)) .WillOnce(SetArgumentPointee<1>(kMaxSamples)) .RetiresOnSaturation(); } EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) .WillOnce(SetArgumentPointee<1>(kNumVertexAttribs)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, _)) .WillOnce(SetArgumentPointee<1>(kNumTextureUnits)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_SIZE, _)) .WillOnce(SetArgumentPointee<1>(kMaxTextureSize)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, _)) .WillOnce(SetArgumentPointee<1>(kMaxCubeMapTextureSize)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, _)) .WillOnce(SetArgumentPointee<1>(kMaxTextureImageUnits)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, _)) .WillOnce(SetArgumentPointee<1>(kMaxVertexTextureImageUnits)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _)) .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _)) .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _)) .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents)) .RetiresOnSaturation(); bool use_default_textures = bind_generates_resource; SetupTextureManagerInitExpectations(gl, extensions, use_default_textures); } void TestHelper::SetupFeatureInfoInitExpectations( ::gfx::MockGLInterface* gl, const char* extensions) { SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", ""); } void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( ::gfx::MockGLInterface* gl, const char* extensions, const char* gl_renderer, const char* gl_version) { InSequence sequence; EXPECT_CALL(*gl, GetString(GL_EXTENSIONS)) .WillOnce(Return(reinterpret_cast(extensions))) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetString(GL_RENDERER)) .WillOnce(Return(reinterpret_cast(gl_renderer))) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetString(GL_VERSION)) .WillOnce(Return(reinterpret_cast(gl_version))) .RetiresOnSaturation(); std::string l_version(StringToLowerASCII(std::string(gl_version))); bool is_es3 = (l_version.substr(0, 12) == "opengl es 3."); if (strstr(extensions, "GL_ARB_texture_float") || (is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) { static const GLuint gl_ids[] = {101, 102}; const GLsizei width = 16; EXPECT_CALL(*gl, GetIntegerv(GL_FRAMEBUFFER_BINDING, _)) .WillOnce(SetArgumentPointee<1>(gl_ids[0])) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_TEXTURE_BINDING_2D, _)) .WillOnce(SetArgumentPointee<1>(gl_ids[0])) .RetiresOnSaturation(); EXPECT_CALL(*gl, GenTextures(1, _)) .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GenFramebuffersEXT(1, _)) .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2)) .RetiresOnSaturation(); EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[1])) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, GL_RGBA, GL_FLOAT, _)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[1])) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, FramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl_ids[1], 0)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, GL_RGB, GL_FLOAT, _)) .Times(1) .RetiresOnSaturation(); if (is_es3) { EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)) .RetiresOnSaturation(); } else { EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); } EXPECT_CALL(*gl, DeleteFramebuffersEXT(1, _)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, DeleteTextures(1, _)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[0])) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[0])) .Times(1) .RetiresOnSaturation(); #if DCHECK_IS_ON EXPECT_CALL(*gl, GetError()) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); #endif } } void TestHelper::SetupExpectationsForClearingUniforms( ::gfx::MockGLInterface* gl, UniformInfo* uniforms, size_t num_uniforms) { for (size_t ii = 0; ii < num_uniforms; ++ii) { const UniformInfo& info = uniforms[ii]; switch (info.type) { case GL_FLOAT: EXPECT_CALL(*gl, Uniform1fv(info.real_location, info.size, _)) .Times(1) .RetiresOnSaturation(); break; case GL_FLOAT_VEC2: EXPECT_CALL(*gl, Uniform2fv(info.real_location, info.size, _)) .Times(1) .RetiresOnSaturation(); break; case GL_FLOAT_VEC3: EXPECT_CALL(*gl, Uniform3fv(info.real_location, info.size, _)) .Times(1) .RetiresOnSaturation(); break; case GL_FLOAT_VEC4: EXPECT_CALL(*gl, Uniform4fv(info.real_location, info.size, _)) .Times(1) .RetiresOnSaturation(); break; case GL_INT: case GL_BOOL: case GL_SAMPLER_2D: case GL_SAMPLER_CUBE: case GL_SAMPLER_EXTERNAL_OES: case GL_SAMPLER_3D_OES: case GL_SAMPLER_2D_RECT_ARB: EXPECT_CALL(*gl, Uniform1iv(info.real_location, info.size, _)) .Times(1) .RetiresOnSaturation(); break; case GL_INT_VEC2: case GL_BOOL_VEC2: EXPECT_CALL(*gl, Uniform2iv(info.real_location, info.size, _)) .Times(1) .RetiresOnSaturation(); break; case GL_INT_VEC3: case GL_BOOL_VEC3: EXPECT_CALL(*gl, Uniform3iv(info.real_location, info.size, _)) .Times(1) .RetiresOnSaturation(); break; case GL_INT_VEC4: case GL_BOOL_VEC4: EXPECT_CALL(*gl, Uniform4iv(info.real_location, info.size, _)) .Times(1) .RetiresOnSaturation(); break; case GL_FLOAT_MAT2: EXPECT_CALL(*gl, UniformMatrix2fv( info.real_location, info.size, false, _)) .Times(1) .RetiresOnSaturation(); break; case GL_FLOAT_MAT3: EXPECT_CALL(*gl, UniformMatrix3fv( info.real_location, info.size, false, _)) .Times(1) .RetiresOnSaturation(); break; case GL_FLOAT_MAT4: EXPECT_CALL(*gl, UniformMatrix4fv( info.real_location, info.size, false, _)) .Times(1) .RetiresOnSaturation(); break; default: NOTREACHED(); break; } } } void TestHelper::SetupProgramSuccessExpectations( ::gfx::MockGLInterface* gl, AttribInfo* attribs, size_t num_attribs, UniformInfo* uniforms, size_t num_uniforms, GLuint service_id) { EXPECT_CALL(*gl, GetProgramiv(service_id, GL_LINK_STATUS, _)) .WillOnce(SetArgumentPointee<2>(1)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetProgramiv(service_id, GL_INFO_LOG_LENGTH, _)) .WillOnce(SetArgumentPointee<2>(0)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _)) .WillOnce(SetArgumentPointee<2>(num_attribs)) .RetiresOnSaturation(); size_t max_attrib_len = 0; for (size_t ii = 0; ii < num_attribs; ++ii) { size_t len = strlen(attribs[ii].name) + 1; max_attrib_len = std::max(max_attrib_len, len); } EXPECT_CALL(*gl, GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _)) .WillOnce(SetArgumentPointee<2>(max_attrib_len)) .RetiresOnSaturation(); for (size_t ii = 0; ii < num_attribs; ++ii) { const AttribInfo& info = attribs[ii]; EXPECT_CALL(*gl, GetActiveAttrib(service_id, ii, max_attrib_len, _, _, _, _)) .WillOnce(DoAll( SetArgumentPointee<3>(strlen(info.name)), SetArgumentPointee<4>(info.size), SetArgumentPointee<5>(info.type), SetArrayArgument<6>(info.name, info.name + strlen(info.name) + 1))) .RetiresOnSaturation(); if (!ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) { EXPECT_CALL(*gl, GetAttribLocation(service_id, StrEq(info.name))) .WillOnce(Return(info.location)) .RetiresOnSaturation(); } } EXPECT_CALL(*gl, GetProgramiv(service_id, GL_ACTIVE_UNIFORMS, _)) .WillOnce(SetArgumentPointee<2>(num_uniforms)) .RetiresOnSaturation(); size_t max_uniform_len = 0; for (size_t ii = 0; ii < num_uniforms; ++ii) { size_t len = strlen(uniforms[ii].name) + 1; max_uniform_len = std::max(max_uniform_len, len); } EXPECT_CALL(*gl, GetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, _)) .WillOnce(SetArgumentPointee<2>(max_uniform_len)) .RetiresOnSaturation(); for (size_t ii = 0; ii < num_uniforms; ++ii) { const UniformInfo& info = uniforms[ii]; EXPECT_CALL(*gl, GetActiveUniform(service_id, ii, max_uniform_len, _, _, _, _)) .WillOnce(DoAll( SetArgumentPointee<3>(strlen(info.name)), SetArgumentPointee<4>(info.size), SetArgumentPointee<5>(info.type), SetArrayArgument<6>(info.name, info.name + strlen(info.name) + 1))) .RetiresOnSaturation(); } for (int pass = 0; pass < 2; ++pass) { for (size_t ii = 0; ii < num_uniforms; ++ii) { const UniformInfo& info = uniforms[ii]; if (ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) { continue; } if (pass == 0) { EXPECT_CALL(*gl, GetUniformLocation(service_id, StrEq(info.name))) .WillOnce(Return(info.real_location)) .RetiresOnSaturation(); } if ((pass == 0 && info.desired_location >= 0) || (pass == 1 && info.desired_location < 0)) { if (info.size > 1) { std::string base_name = info.name; size_t array_pos = base_name.rfind("[0]"); if (base_name.size() > 3 && array_pos == base_name.size() - 3) { base_name = base_name.substr(0, base_name.size() - 3); } for (GLsizei jj = 1; jj < info.size; ++jj) { std::string element_name( std::string(base_name) + "[" + base::IntToString(jj) + "]"); EXPECT_CALL(*gl, GetUniformLocation( service_id, StrEq(element_name))) .WillOnce(Return(info.real_location + jj * 2)) .RetiresOnSaturation(); } } } } } } void TestHelper::SetupShader( ::gfx::MockGLInterface* gl, AttribInfo* attribs, size_t num_attribs, UniformInfo* uniforms, size_t num_uniforms, GLuint service_id) { InSequence s; EXPECT_CALL(*gl, LinkProgram(service_id)) .Times(1) .RetiresOnSaturation(); SetupProgramSuccessExpectations( gl, attribs, num_attribs, uniforms, num_uniforms, service_id); } void TestHelper::DoBufferData( ::gfx::MockGLInterface* gl, MockErrorState* error_state, BufferManager* manager, Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data, GLenum error) { EXPECT_CALL(*error_state, CopyRealGLErrorsToWrapper(_, _, _)) .Times(1) .RetiresOnSaturation(); if (manager->IsUsageClientSideArray(usage)) { EXPECT_CALL(*gl, BufferData( buffer->target(), 0, _, usage)) .Times(1) .RetiresOnSaturation(); } else { EXPECT_CALL(*gl, BufferData( buffer->target(), size, _, usage)) .Times(1) .RetiresOnSaturation(); } EXPECT_CALL(*error_state, PeekGLError(_, _, _)) .WillOnce(Return(error)) .RetiresOnSaturation(); manager->DoBufferData(error_state, buffer, size, usage, data); } void TestHelper::SetTexParameteriWithExpectations( ::gfx::MockGLInterface* gl, MockErrorState* error_state, TextureManager* manager, TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) { if (error == GL_NO_ERROR) { if (pname != GL_TEXTURE_POOL_CHROMIUM) { EXPECT_CALL(*gl, TexParameteri(texture_ref->texture()->target(), pname, value)) .Times(1) .RetiresOnSaturation(); } } else if (error == GL_INVALID_ENUM) { EXPECT_CALL(*error_state, SetGLErrorInvalidEnum(_, _, _, value, _)) .Times(1) .RetiresOnSaturation(); } else { EXPECT_CALL(*error_state, SetGLErrorInvalidParami(_, _, error, _, _, _)) .Times(1) .RetiresOnSaturation(); } manager->SetParameteri("", error_state, texture_ref, pname, value); } ScopedGLImplementationSetter::ScopedGLImplementationSetter( gfx::GLImplementation implementation) : old_implementation_(gfx::GetGLImplementation()) { gfx::SetGLImplementation(implementation); } ScopedGLImplementationSetter::~ScopedGLImplementationSetter() { gfx::SetGLImplementation(old_implementation_); } } // namespace gles2 } // namespace gpu