1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "gpu/command_buffer/service/test_helper.h" 6 7 #include <algorithm> 8 #include <string> 9 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_tokenizer.h" 12 #include "gpu/command_buffer/common/types.h" 13 #include "gpu/command_buffer/service/buffer_manager.h" 14 #include "gpu/command_buffer/service/error_state_mock.h" 15 #include "gpu/command_buffer/service/gl_utils.h" 16 #include "gpu/command_buffer/service/gpu_switches.h" 17 #include "gpu/command_buffer/service/program_manager.h" 18 #include "gpu/command_buffer/service/texture_manager.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 #include "ui/gl/gl_mock.h" 21 22 using ::testing::_; 23 using ::testing::DoAll; 24 using ::testing::InSequence; 25 using ::testing::MatcherCast; 26 using ::testing::Pointee; 27 using ::testing::Return; 28 using ::testing::SetArrayArgument; 29 using ::testing::SetArgumentPointee; 30 using ::testing::StrEq; 31 using ::testing::StrictMock; 32 33 namespace gpu { 34 namespace gles2 { 35 36 // GCC requires these declarations, but MSVC requires they not be present 37 #ifndef COMPILER_MSVC 38 const GLuint TestHelper::kServiceBlackTexture2dId; 39 const GLuint TestHelper::kServiceDefaultTexture2dId; 40 const GLuint TestHelper::kServiceBlackTextureCubemapId; 41 const GLuint TestHelper::kServiceDefaultTextureCubemapId; 42 const GLuint TestHelper::kServiceBlackExternalTextureId; 43 const GLuint TestHelper::kServiceDefaultExternalTextureId; 44 const GLuint TestHelper::kServiceBlackRectangleTextureId; 45 const GLuint TestHelper::kServiceDefaultRectangleTextureId; 46 47 const GLint TestHelper::kMaxSamples; 48 const GLint TestHelper::kMaxRenderbufferSize; 49 const GLint TestHelper::kMaxTextureSize; 50 const GLint TestHelper::kMaxCubeMapTextureSize; 51 const GLint TestHelper::kNumVertexAttribs; 52 const GLint TestHelper::kNumTextureUnits; 53 const GLint TestHelper::kMaxTextureImageUnits; 54 const GLint TestHelper::kMaxVertexTextureImageUnits; 55 const GLint TestHelper::kMaxFragmentUniformVectors; 56 const GLint TestHelper::kMaxFragmentUniformComponents; 57 const GLint TestHelper::kMaxVaryingVectors; 58 const GLint TestHelper::kMaxVaryingFloats; 59 const GLint TestHelper::kMaxVertexUniformVectors; 60 const GLint TestHelper::kMaxVertexUniformComponents; 61 #endif 62 63 void TestHelper::SetupTextureInitializationExpectations( 64 ::gfx::MockGLInterface* gl, GLenum target) { 65 InSequence sequence; 66 67 bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); 68 bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); 69 70 static GLuint texture_2d_ids[] = { 71 kServiceBlackTexture2dId, 72 kServiceDefaultTexture2dId }; 73 static GLuint texture_cube_map_ids[] = { 74 kServiceBlackTextureCubemapId, 75 kServiceDefaultTextureCubemapId }; 76 static GLuint texture_external_oes_ids[] = { 77 kServiceBlackExternalTextureId, 78 kServiceDefaultExternalTextureId }; 79 static GLuint texture_rectangle_arb_ids[] = { 80 kServiceBlackRectangleTextureId, 81 kServiceDefaultRectangleTextureId }; 82 83 const GLuint* texture_ids = NULL; 84 switch (target) { 85 case GL_TEXTURE_2D: 86 texture_ids = &texture_2d_ids[0]; 87 break; 88 case GL_TEXTURE_CUBE_MAP: 89 texture_ids = &texture_cube_map_ids[0]; 90 break; 91 case GL_TEXTURE_EXTERNAL_OES: 92 texture_ids = &texture_external_oes_ids[0]; 93 break; 94 case GL_TEXTURE_RECTANGLE_ARB: 95 texture_ids = &texture_rectangle_arb_ids[0]; 96 break; 97 default: 98 NOTREACHED(); 99 } 100 101 int array_size = 2; 102 103 EXPECT_CALL(*gl, GenTextures(array_size, _)) 104 .WillOnce(SetArrayArgument<1>(texture_ids, 105 texture_ids + array_size)) 106 .RetiresOnSaturation(); 107 for (int ii = 0; ii < array_size; ++ii) { 108 EXPECT_CALL(*gl, BindTexture(target, texture_ids[ii])) 109 .Times(1) 110 .RetiresOnSaturation(); 111 if (needs_initialization) { 112 if (needs_faces) { 113 static GLenum faces[] = { 114 GL_TEXTURE_CUBE_MAP_POSITIVE_X, 115 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 116 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 117 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 118 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 119 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 120 }; 121 for (size_t ii = 0; ii < arraysize(faces); ++ii) { 122 EXPECT_CALL(*gl, TexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA, 123 GL_UNSIGNED_BYTE, _)) 124 .Times(1) 125 .RetiresOnSaturation(); 126 } 127 } else { 128 EXPECT_CALL(*gl, TexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, 129 GL_UNSIGNED_BYTE, _)) 130 .Times(1) 131 .RetiresOnSaturation(); 132 } 133 } 134 } 135 EXPECT_CALL(*gl, BindTexture(target, 0)) 136 .Times(1) 137 .RetiresOnSaturation(); 138 } 139 140 void TestHelper::SetupTextureManagerInitExpectations( 141 ::gfx::MockGLInterface* gl, 142 const char* extensions) { 143 InSequence sequence; 144 145 SetupTextureInitializationExpectations(gl, GL_TEXTURE_2D); 146 SetupTextureInitializationExpectations(gl, GL_TEXTURE_CUBE_MAP); 147 148 bool ext_image_external = false; 149 bool arb_texture_rectangle = false; 150 base::CStringTokenizer t(extensions, extensions + strlen(extensions), " "); 151 while (t.GetNext()) { 152 if (t.token() == "GL_OES_EGL_image_external") { 153 ext_image_external = true; 154 break; 155 } 156 if (t.token() == "GL_ARB_texture_rectangle") { 157 arb_texture_rectangle = true; 158 break; 159 } 160 } 161 162 if (ext_image_external) { 163 SetupTextureInitializationExpectations(gl, GL_TEXTURE_EXTERNAL_OES); 164 } 165 if (arb_texture_rectangle) { 166 SetupTextureInitializationExpectations(gl, GL_TEXTURE_RECTANGLE_ARB); 167 } 168 } 169 170 void TestHelper::SetupTextureDestructionExpectations( 171 ::gfx::MockGLInterface* gl, GLenum target) { 172 GLuint texture_id = 0; 173 switch (target) { 174 case GL_TEXTURE_2D: 175 texture_id = kServiceDefaultTexture2dId; 176 break; 177 case GL_TEXTURE_CUBE_MAP: 178 texture_id = kServiceDefaultTextureCubemapId; 179 break; 180 case GL_TEXTURE_EXTERNAL_OES: 181 texture_id = kServiceDefaultExternalTextureId; 182 break; 183 case GL_TEXTURE_RECTANGLE_ARB: 184 texture_id = kServiceDefaultRectangleTextureId; 185 break; 186 default: 187 NOTREACHED(); 188 } 189 190 EXPECT_CALL(*gl, DeleteTextures(1, Pointee(texture_id))) 191 .Times(1) 192 .RetiresOnSaturation(); 193 } 194 195 void TestHelper::SetupTextureManagerDestructionExpectations( 196 ::gfx::MockGLInterface* gl, 197 const char* extensions) { 198 SetupTextureDestructionExpectations(gl, GL_TEXTURE_2D); 199 SetupTextureDestructionExpectations(gl, GL_TEXTURE_CUBE_MAP); 200 201 bool ext_image_external = false; 202 bool arb_texture_rectangle = false; 203 base::CStringTokenizer t(extensions, extensions + strlen(extensions), " "); 204 while (t.GetNext()) { 205 if (t.token() == "GL_OES_EGL_image_external") { 206 ext_image_external = true; 207 break; 208 } 209 if (t.token() == "GL_ARB_texture_rectangle") { 210 arb_texture_rectangle = true; 211 break; 212 } 213 } 214 215 if (ext_image_external) { 216 SetupTextureDestructionExpectations(gl, GL_TEXTURE_EXTERNAL_OES); 217 } 218 if (arb_texture_rectangle) { 219 SetupTextureDestructionExpectations(gl, GL_TEXTURE_RECTANGLE_ARB); 220 } 221 222 EXPECT_CALL(*gl, DeleteTextures(4, _)) 223 .Times(1) 224 .RetiresOnSaturation(); 225 } 226 227 void TestHelper::SetupContextGroupInitExpectations( 228 ::gfx::MockGLInterface* gl, 229 const DisallowedFeatures& disallowed_features, 230 const char* extensions) { 231 InSequence sequence; 232 233 SetupFeatureInfoInitExpectations(gl, extensions); 234 235 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _)) 236 .WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize)) 237 .RetiresOnSaturation(); 238 if (strstr(extensions, "GL_EXT_framebuffer_multisample") || 239 strstr(extensions, "GL_EXT_multisampled_render_to_texture")) { 240 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _)) 241 .WillOnce(SetArgumentPointee<1>(kMaxSamples)) 242 .RetiresOnSaturation(); 243 } else if (strstr(extensions, "GL_IMG_multisampled_render_to_texture")) { 244 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES_IMG, _)) 245 .WillOnce(SetArgumentPointee<1>(kMaxSamples)) 246 .RetiresOnSaturation(); 247 } 248 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) 249 .WillOnce(SetArgumentPointee<1>(kNumVertexAttribs)) 250 .RetiresOnSaturation(); 251 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, _)) 252 .WillOnce(SetArgumentPointee<1>(kNumTextureUnits)) 253 .RetiresOnSaturation(); 254 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_SIZE, _)) 255 .WillOnce(SetArgumentPointee<1>(kMaxTextureSize)) 256 .RetiresOnSaturation(); 257 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, _)) 258 .WillOnce(SetArgumentPointee<1>(kMaxCubeMapTextureSize)) 259 .RetiresOnSaturation(); 260 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, _)) 261 .WillOnce(SetArgumentPointee<1>(kMaxTextureImageUnits)) 262 .RetiresOnSaturation(); 263 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, _)) 264 .WillOnce(SetArgumentPointee<1>(kMaxVertexTextureImageUnits)) 265 .RetiresOnSaturation(); 266 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _)) 267 .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents)) 268 .RetiresOnSaturation(); 269 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _)) 270 .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats)) 271 .RetiresOnSaturation(); 272 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _)) 273 .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents)) 274 .RetiresOnSaturation(); 275 276 SetupTextureManagerInitExpectations(gl, extensions); 277 } 278 279 void TestHelper::SetupFeatureInfoInitExpectations( 280 ::gfx::MockGLInterface* gl, const char* extensions) { 281 SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", ""); 282 } 283 284 void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( 285 ::gfx::MockGLInterface* gl, 286 const char* extensions, 287 const char* gl_renderer, 288 const char* gl_version) { 289 InSequence sequence; 290 291 EXPECT_CALL(*gl, GetString(GL_EXTENSIONS)) 292 .WillOnce(Return(reinterpret_cast<const uint8*>(extensions))) 293 .RetiresOnSaturation(); 294 EXPECT_CALL(*gl, GetString(GL_RENDERER)) 295 .WillOnce(Return(reinterpret_cast<const uint8*>(gl_renderer))) 296 .RetiresOnSaturation(); 297 EXPECT_CALL(*gl, GetString(GL_VERSION)) 298 .WillOnce(Return(reinterpret_cast<const uint8*>(gl_version))) 299 .RetiresOnSaturation(); 300 } 301 302 void TestHelper::SetupExpectationsForClearingUniforms( 303 ::gfx::MockGLInterface* gl, UniformInfo* uniforms, size_t num_uniforms) { 304 for (size_t ii = 0; ii < num_uniforms; ++ii) { 305 const UniformInfo& info = uniforms[ii]; 306 switch (info.type) { 307 case GL_FLOAT: 308 EXPECT_CALL(*gl, Uniform1fv(info.real_location, info.size, _)) 309 .Times(1) 310 .RetiresOnSaturation(); 311 break; 312 case GL_FLOAT_VEC2: 313 EXPECT_CALL(*gl, Uniform2fv(info.real_location, info.size, _)) 314 .Times(1) 315 .RetiresOnSaturation(); 316 break; 317 case GL_FLOAT_VEC3: 318 EXPECT_CALL(*gl, Uniform3fv(info.real_location, info.size, _)) 319 .Times(1) 320 .RetiresOnSaturation(); 321 break; 322 case GL_FLOAT_VEC4: 323 EXPECT_CALL(*gl, Uniform4fv(info.real_location, info.size, _)) 324 .Times(1) 325 .RetiresOnSaturation(); 326 break; 327 case GL_INT: 328 case GL_BOOL: 329 case GL_SAMPLER_2D: 330 case GL_SAMPLER_CUBE: 331 case GL_SAMPLER_EXTERNAL_OES: 332 case GL_SAMPLER_3D_OES: 333 case GL_SAMPLER_2D_RECT_ARB: 334 EXPECT_CALL(*gl, Uniform1iv(info.real_location, info.size, _)) 335 .Times(1) 336 .RetiresOnSaturation(); 337 break; 338 case GL_INT_VEC2: 339 case GL_BOOL_VEC2: 340 EXPECT_CALL(*gl, Uniform2iv(info.real_location, info.size, _)) 341 .Times(1) 342 .RetiresOnSaturation(); 343 break; 344 case GL_INT_VEC3: 345 case GL_BOOL_VEC3: 346 EXPECT_CALL(*gl, Uniform3iv(info.real_location, info.size, _)) 347 .Times(1) 348 .RetiresOnSaturation(); 349 break; 350 case GL_INT_VEC4: 351 case GL_BOOL_VEC4: 352 EXPECT_CALL(*gl, Uniform4iv(info.real_location, info.size, _)) 353 .Times(1) 354 .RetiresOnSaturation(); 355 break; 356 case GL_FLOAT_MAT2: 357 EXPECT_CALL(*gl, UniformMatrix2fv( 358 info.real_location, info.size, false, _)) 359 .Times(1) 360 .RetiresOnSaturation(); 361 break; 362 case GL_FLOAT_MAT3: 363 EXPECT_CALL(*gl, UniformMatrix3fv( 364 info.real_location, info.size, false, _)) 365 .Times(1) 366 .RetiresOnSaturation(); 367 break; 368 case GL_FLOAT_MAT4: 369 EXPECT_CALL(*gl, UniformMatrix4fv( 370 info.real_location, info.size, false, _)) 371 .Times(1) 372 .RetiresOnSaturation(); 373 break; 374 default: 375 NOTREACHED(); 376 break; 377 } 378 } 379 } 380 381 void TestHelper::SetupProgramSuccessExpectations( 382 ::gfx::MockGLInterface* gl, 383 AttribInfo* attribs, size_t num_attribs, 384 UniformInfo* uniforms, size_t num_uniforms, 385 GLuint service_id) { 386 EXPECT_CALL(*gl, 387 GetProgramiv(service_id, GL_LINK_STATUS, _)) 388 .WillOnce(SetArgumentPointee<2>(1)) 389 .RetiresOnSaturation(); 390 EXPECT_CALL(*gl, 391 GetProgramiv(service_id, GL_INFO_LOG_LENGTH, _)) 392 .WillOnce(SetArgumentPointee<2>(0)) 393 .RetiresOnSaturation(); 394 EXPECT_CALL(*gl, 395 GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _)) 396 .WillOnce(SetArgumentPointee<2>(num_attribs)) 397 .RetiresOnSaturation(); 398 size_t max_attrib_len = 0; 399 for (size_t ii = 0; ii < num_attribs; ++ii) { 400 size_t len = strlen(attribs[ii].name) + 1; 401 max_attrib_len = std::max(max_attrib_len, len); 402 } 403 EXPECT_CALL(*gl, 404 GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _)) 405 .WillOnce(SetArgumentPointee<2>(max_attrib_len)) 406 .RetiresOnSaturation(); 407 408 for (size_t ii = 0; ii < num_attribs; ++ii) { 409 const AttribInfo& info = attribs[ii]; 410 EXPECT_CALL(*gl, 411 GetActiveAttrib(service_id, ii, 412 max_attrib_len, _, _, _, _)) 413 .WillOnce(DoAll( 414 SetArgumentPointee<3>(strlen(info.name)), 415 SetArgumentPointee<4>(info.size), 416 SetArgumentPointee<5>(info.type), 417 SetArrayArgument<6>(info.name, 418 info.name + strlen(info.name) + 1))) 419 .RetiresOnSaturation(); 420 if (!ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) { 421 EXPECT_CALL(*gl, GetAttribLocation(service_id, StrEq(info.name))) 422 .WillOnce(Return(info.location)) 423 .RetiresOnSaturation(); 424 } 425 } 426 EXPECT_CALL(*gl, 427 GetProgramiv(service_id, GL_ACTIVE_UNIFORMS, _)) 428 .WillOnce(SetArgumentPointee<2>(num_uniforms)) 429 .RetiresOnSaturation(); 430 431 size_t max_uniform_len = 0; 432 for (size_t ii = 0; ii < num_uniforms; ++ii) { 433 size_t len = strlen(uniforms[ii].name) + 1; 434 max_uniform_len = std::max(max_uniform_len, len); 435 } 436 EXPECT_CALL(*gl, 437 GetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, _)) 438 .WillOnce(SetArgumentPointee<2>(max_uniform_len)) 439 .RetiresOnSaturation(); 440 for (size_t ii = 0; ii < num_uniforms; ++ii) { 441 const UniformInfo& info = uniforms[ii]; 442 EXPECT_CALL(*gl, 443 GetActiveUniform(service_id, ii, 444 max_uniform_len, _, _, _, _)) 445 .WillOnce(DoAll( 446 SetArgumentPointee<3>(strlen(info.name)), 447 SetArgumentPointee<4>(info.size), 448 SetArgumentPointee<5>(info.type), 449 SetArrayArgument<6>(info.name, 450 info.name + strlen(info.name) + 1))) 451 .RetiresOnSaturation(); 452 } 453 454 for (int pass = 0; pass < 2; ++pass) { 455 for (size_t ii = 0; ii < num_uniforms; ++ii) { 456 const UniformInfo& info = uniforms[ii]; 457 if (ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) { 458 continue; 459 } 460 if (pass == 0) { 461 EXPECT_CALL(*gl, GetUniformLocation(service_id, StrEq(info.name))) 462 .WillOnce(Return(info.real_location)) 463 .RetiresOnSaturation(); 464 } 465 if ((pass == 0 && info.desired_location >= 0) || 466 (pass == 1 && info.desired_location < 0)) { 467 if (info.size > 1) { 468 std::string base_name = info.name; 469 size_t array_pos = base_name.rfind("[0]"); 470 if (base_name.size() > 3 && array_pos == base_name.size() - 3) { 471 base_name = base_name.substr(0, base_name.size() - 3); 472 } 473 for (GLsizei jj = 1; jj < info.size; ++jj) { 474 std::string element_name( 475 std::string(base_name) + "[" + base::IntToString(jj) + "]"); 476 EXPECT_CALL(*gl, GetUniformLocation( 477 service_id, StrEq(element_name))) 478 .WillOnce(Return(info.real_location + jj * 2)) 479 .RetiresOnSaturation(); 480 } 481 } 482 } 483 } 484 } 485 } 486 487 void TestHelper::SetupShader( 488 ::gfx::MockGLInterface* gl, 489 AttribInfo* attribs, size_t num_attribs, 490 UniformInfo* uniforms, size_t num_uniforms, 491 GLuint service_id) { 492 InSequence s; 493 494 EXPECT_CALL(*gl, 495 LinkProgram(service_id)) 496 .Times(1) 497 .RetiresOnSaturation(); 498 499 SetupProgramSuccessExpectations( 500 gl, attribs, num_attribs, uniforms, num_uniforms, service_id); 501 } 502 503 void TestHelper::DoBufferData( 504 ::gfx::MockGLInterface* gl, MockErrorState* error_state, 505 BufferManager* manager, Buffer* buffer, GLsizeiptr size, GLenum usage, 506 const GLvoid* data, GLenum error) { 507 EXPECT_CALL(*error_state, CopyRealGLErrorsToWrapper(_, _, _)) 508 .Times(1) 509 .RetiresOnSaturation(); 510 if (manager->IsUsageClientSideArray(usage)) { 511 EXPECT_CALL(*gl, BufferData( 512 buffer->target(), 0, _, usage)) 513 .Times(1) 514 .RetiresOnSaturation(); 515 } else { 516 EXPECT_CALL(*gl, BufferData( 517 buffer->target(), size, _, usage)) 518 .Times(1) 519 .RetiresOnSaturation(); 520 } 521 EXPECT_CALL(*error_state, PeekGLError(_, _, _)) 522 .WillOnce(Return(error)) 523 .RetiresOnSaturation(); 524 manager->DoBufferData(error_state, buffer, size, usage, data); 525 } 526 527 void TestHelper::SetTexParameterWithExpectations( 528 ::gfx::MockGLInterface* gl, MockErrorState* error_state, 529 TextureManager* manager, TextureRef* texture_ref, 530 GLenum pname, GLint value, GLenum error) { 531 if (error == GL_NO_ERROR) { 532 if (pname != GL_TEXTURE_POOL_CHROMIUM) { 533 EXPECT_CALL(*gl, TexParameteri(texture_ref->texture()->target(), 534 pname, value)) 535 .Times(1) 536 .RetiresOnSaturation(); 537 } 538 } else if (error == GL_INVALID_ENUM) { 539 EXPECT_CALL(*error_state, SetGLErrorInvalidEnum(_, _, _, value, _)) 540 .Times(1) 541 .RetiresOnSaturation(); 542 } else { 543 EXPECT_CALL(*error_state, SetGLErrorInvalidParam(_, _, error, _, _, _)) 544 .Times(1) 545 .RetiresOnSaturation(); 546 } 547 manager->SetParameter("", error_state, texture_ref, pname, value); 548 } 549 550 ScopedGLImplementationSetter::ScopedGLImplementationSetter( 551 gfx::GLImplementation implementation) 552 : old_implementation_(gfx::GetGLImplementation()) { 553 gfx::SetGLImplementation(implementation); 554 } 555 556 ScopedGLImplementationSetter::~ScopedGLImplementationSetter() { 557 gfx::SetGLImplementation(old_implementation_); 558 } 559 560 } // namespace gles2 561 } // namespace gpu 562 563