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/service/buffer_manager.h" 13 #include "gpu/command_buffer/service/error_state_mock.h" 14 #include "gpu/command_buffer/service/gl_utils.h" 15 #include "gpu/command_buffer/service/gpu_switches.h" 16 #include "gpu/command_buffer/service/mocks.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::NotNull; 28 using ::testing::Return; 29 using ::testing::SetArrayArgument; 30 using ::testing::SetArgumentPointee; 31 using ::testing::StrEq; 32 using ::testing::StrictMock; 33 34 namespace gpu { 35 namespace gles2 { 36 37 // GCC requires these declarations, but MSVC requires they not be present 38 #ifndef COMPILER_MSVC 39 const GLuint TestHelper::kServiceBlackTexture2dId; 40 const GLuint TestHelper::kServiceDefaultTexture2dId; 41 const GLuint TestHelper::kServiceBlackTextureCubemapId; 42 const GLuint TestHelper::kServiceDefaultTextureCubemapId; 43 const GLuint TestHelper::kServiceBlackExternalTextureId; 44 const GLuint TestHelper::kServiceDefaultExternalTextureId; 45 const GLuint TestHelper::kServiceBlackRectangleTextureId; 46 const GLuint TestHelper::kServiceDefaultRectangleTextureId; 47 48 const GLint TestHelper::kMaxSamples; 49 const GLint TestHelper::kMaxRenderbufferSize; 50 const GLint TestHelper::kMaxTextureSize; 51 const GLint TestHelper::kMaxCubeMapTextureSize; 52 const GLint TestHelper::kNumVertexAttribs; 53 const GLint TestHelper::kNumTextureUnits; 54 const GLint TestHelper::kMaxTextureImageUnits; 55 const GLint TestHelper::kMaxVertexTextureImageUnits; 56 const GLint TestHelper::kMaxFragmentUniformVectors; 57 const GLint TestHelper::kMaxFragmentUniformComponents; 58 const GLint TestHelper::kMaxVaryingVectors; 59 const GLint TestHelper::kMaxVaryingFloats; 60 const GLint TestHelper::kMaxVertexUniformVectors; 61 const GLint TestHelper::kMaxVertexUniformComponents; 62 #endif 63 64 void TestHelper::SetupTextureInitializationExpectations( 65 ::gfx::MockGLInterface* gl, 66 GLenum target, 67 bool use_default_textures) { 68 InSequence sequence; 69 70 bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); 71 bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); 72 73 static GLuint texture_2d_ids[] = { 74 kServiceBlackTexture2dId, 75 kServiceDefaultTexture2dId }; 76 static GLuint texture_cube_map_ids[] = { 77 kServiceBlackTextureCubemapId, 78 kServiceDefaultTextureCubemapId }; 79 static GLuint texture_external_oes_ids[] = { 80 kServiceBlackExternalTextureId, 81 kServiceDefaultExternalTextureId }; 82 static GLuint texture_rectangle_arb_ids[] = { 83 kServiceBlackRectangleTextureId, 84 kServiceDefaultRectangleTextureId }; 85 86 const GLuint* texture_ids = NULL; 87 switch (target) { 88 case GL_TEXTURE_2D: 89 texture_ids = &texture_2d_ids[0]; 90 break; 91 case GL_TEXTURE_CUBE_MAP: 92 texture_ids = &texture_cube_map_ids[0]; 93 break; 94 case GL_TEXTURE_EXTERNAL_OES: 95 texture_ids = &texture_external_oes_ids[0]; 96 break; 97 case GL_TEXTURE_RECTANGLE_ARB: 98 texture_ids = &texture_rectangle_arb_ids[0]; 99 break; 100 default: 101 NOTREACHED(); 102 } 103 104 int array_size = use_default_textures ? 2 : 1; 105 106 EXPECT_CALL(*gl, GenTextures(array_size, _)) 107 .WillOnce(SetArrayArgument<1>(texture_ids, 108 texture_ids + array_size)) 109 .RetiresOnSaturation(); 110 for (int ii = 0; ii < array_size; ++ii) { 111 EXPECT_CALL(*gl, BindTexture(target, texture_ids[ii])) 112 .Times(1) 113 .RetiresOnSaturation(); 114 if (needs_initialization) { 115 if (needs_faces) { 116 static GLenum faces[] = { 117 GL_TEXTURE_CUBE_MAP_POSITIVE_X, 118 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 119 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 120 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 121 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 122 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 123 }; 124 for (size_t ii = 0; ii < arraysize(faces); ++ii) { 125 EXPECT_CALL(*gl, TexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA, 126 GL_UNSIGNED_BYTE, _)) 127 .Times(1) 128 .RetiresOnSaturation(); 129 } 130 } else { 131 EXPECT_CALL(*gl, TexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, 132 GL_UNSIGNED_BYTE, _)) 133 .Times(1) 134 .RetiresOnSaturation(); 135 } 136 } 137 } 138 EXPECT_CALL(*gl, BindTexture(target, 0)) 139 .Times(1) 140 .RetiresOnSaturation(); 141 } 142 143 void TestHelper::SetupTextureManagerInitExpectations( 144 ::gfx::MockGLInterface* gl, 145 const char* extensions, 146 bool use_default_textures) { 147 InSequence sequence; 148 149 SetupTextureInitializationExpectations( 150 gl, GL_TEXTURE_2D, use_default_textures); 151 SetupTextureInitializationExpectations( 152 gl, GL_TEXTURE_CUBE_MAP, use_default_textures); 153 154 bool ext_image_external = false; 155 bool arb_texture_rectangle = false; 156 base::CStringTokenizer t(extensions, extensions + strlen(extensions), " "); 157 while (t.GetNext()) { 158 if (t.token() == "GL_OES_EGL_image_external") { 159 ext_image_external = true; 160 break; 161 } 162 if (t.token() == "GL_ARB_texture_rectangle") { 163 arb_texture_rectangle = true; 164 break; 165 } 166 } 167 168 if (ext_image_external) { 169 SetupTextureInitializationExpectations( 170 gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures); 171 } 172 if (arb_texture_rectangle) { 173 SetupTextureInitializationExpectations( 174 gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures); 175 } 176 } 177 178 void TestHelper::SetupTextureDestructionExpectations( 179 ::gfx::MockGLInterface* gl, 180 GLenum target, 181 bool use_default_textures) { 182 if (!use_default_textures) 183 return; 184 185 GLuint texture_id = 0; 186 switch (target) { 187 case GL_TEXTURE_2D: 188 texture_id = kServiceDefaultTexture2dId; 189 break; 190 case GL_TEXTURE_CUBE_MAP: 191 texture_id = kServiceDefaultTextureCubemapId; 192 break; 193 case GL_TEXTURE_EXTERNAL_OES: 194 texture_id = kServiceDefaultExternalTextureId; 195 break; 196 case GL_TEXTURE_RECTANGLE_ARB: 197 texture_id = kServiceDefaultRectangleTextureId; 198 break; 199 default: 200 NOTREACHED(); 201 } 202 203 EXPECT_CALL(*gl, DeleteTextures(1, Pointee(texture_id))) 204 .Times(1) 205 .RetiresOnSaturation(); 206 } 207 208 void TestHelper::SetupTextureManagerDestructionExpectations( 209 ::gfx::MockGLInterface* gl, 210 const char* extensions, 211 bool use_default_textures) { 212 SetupTextureDestructionExpectations(gl, GL_TEXTURE_2D, use_default_textures); 213 SetupTextureDestructionExpectations( 214 gl, GL_TEXTURE_CUBE_MAP, use_default_textures); 215 216 bool ext_image_external = false; 217 bool arb_texture_rectangle = false; 218 base::CStringTokenizer t(extensions, extensions + strlen(extensions), " "); 219 while (t.GetNext()) { 220 if (t.token() == "GL_OES_EGL_image_external") { 221 ext_image_external = true; 222 break; 223 } 224 if (t.token() == "GL_ARB_texture_rectangle") { 225 arb_texture_rectangle = true; 226 break; 227 } 228 } 229 230 if (ext_image_external) { 231 SetupTextureDestructionExpectations( 232 gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures); 233 } 234 if (arb_texture_rectangle) { 235 SetupTextureDestructionExpectations( 236 gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures); 237 } 238 239 EXPECT_CALL(*gl, DeleteTextures(4, _)) 240 .Times(1) 241 .RetiresOnSaturation(); 242 } 243 244 void TestHelper::SetupContextGroupInitExpectations( 245 ::gfx::MockGLInterface* gl, 246 const DisallowedFeatures& disallowed_features, 247 const char* extensions, 248 const char* gl_version, 249 bool bind_generates_resource) { 250 InSequence sequence; 251 252 SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", gl_version); 253 254 std::string l_version(base::StringToLowerASCII(std::string(gl_version))); 255 bool is_es3 = (l_version.substr(0, 12) == "opengl es 3."); 256 257 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _)) 258 .WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize)) 259 .RetiresOnSaturation(); 260 if (strstr(extensions, "GL_EXT_framebuffer_multisample") || 261 strstr(extensions, "GL_EXT_multisampled_render_to_texture") || is_es3) { 262 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _)) 263 .WillOnce(SetArgumentPointee<1>(kMaxSamples)) 264 .RetiresOnSaturation(); 265 } else if (strstr(extensions, "GL_IMG_multisampled_render_to_texture")) { 266 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES_IMG, _)) 267 .WillOnce(SetArgumentPointee<1>(kMaxSamples)) 268 .RetiresOnSaturation(); 269 } 270 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) 271 .WillOnce(SetArgumentPointee<1>(kNumVertexAttribs)) 272 .RetiresOnSaturation(); 273 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, _)) 274 .WillOnce(SetArgumentPointee<1>(kNumTextureUnits)) 275 .RetiresOnSaturation(); 276 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_SIZE, _)) 277 .WillOnce(SetArgumentPointee<1>(kMaxTextureSize)) 278 .RetiresOnSaturation(); 279 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, _)) 280 .WillOnce(SetArgumentPointee<1>(kMaxCubeMapTextureSize)) 281 .RetiresOnSaturation(); 282 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, _)) 283 .WillOnce(SetArgumentPointee<1>(kMaxTextureImageUnits)) 284 .RetiresOnSaturation(); 285 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, _)) 286 .WillOnce(SetArgumentPointee<1>(kMaxVertexTextureImageUnits)) 287 .RetiresOnSaturation(); 288 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _)) 289 .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents)) 290 .RetiresOnSaturation(); 291 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _)) 292 .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats)) 293 .RetiresOnSaturation(); 294 EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _)) 295 .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents)) 296 .RetiresOnSaturation(); 297 298 bool use_default_textures = bind_generates_resource; 299 SetupTextureManagerInitExpectations(gl, extensions, use_default_textures); 300 } 301 302 void TestHelper::SetupFeatureInfoInitExpectations( 303 ::gfx::MockGLInterface* gl, const char* extensions) { 304 SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", ""); 305 } 306 307 void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( 308 ::gfx::MockGLInterface* gl, 309 const char* extensions, 310 const char* gl_renderer, 311 const char* gl_version) { 312 InSequence sequence; 313 314 EXPECT_CALL(*gl, GetString(GL_EXTENSIONS)) 315 .WillOnce(Return(reinterpret_cast<const uint8*>(extensions))) 316 .RetiresOnSaturation(); 317 EXPECT_CALL(*gl, GetString(GL_RENDERER)) 318 .WillOnce(Return(reinterpret_cast<const uint8*>(gl_renderer))) 319 .RetiresOnSaturation(); 320 EXPECT_CALL(*gl, GetString(GL_VERSION)) 321 .WillOnce(Return(reinterpret_cast<const uint8*>(gl_version))) 322 .RetiresOnSaturation(); 323 324 std::string l_version(base::StringToLowerASCII(std::string(gl_version))); 325 bool is_es3 = (l_version.substr(0, 12) == "opengl es 3."); 326 327 if (strstr(extensions, "GL_ARB_texture_float") || 328 (is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) { 329 static const GLuint gl_ids[] = {101, 102}; 330 const GLsizei width = 16; 331 EXPECT_CALL(*gl, GetIntegerv(GL_FRAMEBUFFER_BINDING, _)) 332 .WillOnce(SetArgumentPointee<1>(gl_ids[0])) 333 .RetiresOnSaturation(); 334 EXPECT_CALL(*gl, GetIntegerv(GL_TEXTURE_BINDING_2D, _)) 335 .WillOnce(SetArgumentPointee<1>(gl_ids[0])) 336 .RetiresOnSaturation(); 337 EXPECT_CALL(*gl, GenTextures(1, _)) 338 .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2)) 339 .RetiresOnSaturation(); 340 EXPECT_CALL(*gl, GenFramebuffersEXT(1, _)) 341 .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2)) 342 .RetiresOnSaturation(); 343 EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[1])) 344 .Times(1) 345 .RetiresOnSaturation(); 346 EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 347 GL_NEAREST)) 348 .Times(1) 349 .RetiresOnSaturation(); 350 EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, 351 GL_RGBA, GL_FLOAT, _)) 352 .Times(1) 353 .RetiresOnSaturation(); 354 EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[1])) 355 .Times(1) 356 .RetiresOnSaturation(); 357 EXPECT_CALL(*gl, FramebufferTexture2DEXT(GL_FRAMEBUFFER, 358 GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl_ids[1], 0)) 359 .Times(1) 360 .RetiresOnSaturation(); 361 EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) 362 .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) 363 .RetiresOnSaturation(); 364 EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, 365 GL_RGB, GL_FLOAT, _)) 366 .Times(1) 367 .RetiresOnSaturation(); 368 if (is_es3) { 369 EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) 370 .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)) 371 .RetiresOnSaturation(); 372 } else { 373 EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) 374 .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) 375 .RetiresOnSaturation(); 376 } 377 EXPECT_CALL(*gl, DeleteFramebuffersEXT(1, _)) 378 .Times(1) 379 .RetiresOnSaturation(); 380 EXPECT_CALL(*gl, DeleteTextures(1, _)) 381 .Times(1) 382 .RetiresOnSaturation(); 383 EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[0])) 384 .Times(1) 385 .RetiresOnSaturation(); 386 EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[0])) 387 .Times(1) 388 .RetiresOnSaturation(); 389 #if DCHECK_IS_ON 390 EXPECT_CALL(*gl, GetError()) 391 .WillOnce(Return(GL_NO_ERROR)) 392 .RetiresOnSaturation(); 393 #endif 394 } 395 } 396 397 void TestHelper::SetupExpectationsForClearingUniforms( 398 ::gfx::MockGLInterface* gl, UniformInfo* uniforms, size_t num_uniforms) { 399 for (size_t ii = 0; ii < num_uniforms; ++ii) { 400 const UniformInfo& info = uniforms[ii]; 401 switch (info.type) { 402 case GL_FLOAT: 403 EXPECT_CALL(*gl, Uniform1fv(info.real_location, info.size, _)) 404 .Times(1) 405 .RetiresOnSaturation(); 406 break; 407 case GL_FLOAT_VEC2: 408 EXPECT_CALL(*gl, Uniform2fv(info.real_location, info.size, _)) 409 .Times(1) 410 .RetiresOnSaturation(); 411 break; 412 case GL_FLOAT_VEC3: 413 EXPECT_CALL(*gl, Uniform3fv(info.real_location, info.size, _)) 414 .Times(1) 415 .RetiresOnSaturation(); 416 break; 417 case GL_FLOAT_VEC4: 418 EXPECT_CALL(*gl, Uniform4fv(info.real_location, info.size, _)) 419 .Times(1) 420 .RetiresOnSaturation(); 421 break; 422 case GL_INT: 423 case GL_BOOL: 424 case GL_SAMPLER_2D: 425 case GL_SAMPLER_CUBE: 426 case GL_SAMPLER_EXTERNAL_OES: 427 case GL_SAMPLER_3D_OES: 428 case GL_SAMPLER_2D_RECT_ARB: 429 EXPECT_CALL(*gl, Uniform1iv(info.real_location, info.size, _)) 430 .Times(1) 431 .RetiresOnSaturation(); 432 break; 433 case GL_INT_VEC2: 434 case GL_BOOL_VEC2: 435 EXPECT_CALL(*gl, Uniform2iv(info.real_location, info.size, _)) 436 .Times(1) 437 .RetiresOnSaturation(); 438 break; 439 case GL_INT_VEC3: 440 case GL_BOOL_VEC3: 441 EXPECT_CALL(*gl, Uniform3iv(info.real_location, info.size, _)) 442 .Times(1) 443 .RetiresOnSaturation(); 444 break; 445 case GL_INT_VEC4: 446 case GL_BOOL_VEC4: 447 EXPECT_CALL(*gl, Uniform4iv(info.real_location, info.size, _)) 448 .Times(1) 449 .RetiresOnSaturation(); 450 break; 451 case GL_FLOAT_MAT2: 452 EXPECT_CALL(*gl, UniformMatrix2fv( 453 info.real_location, info.size, false, _)) 454 .Times(1) 455 .RetiresOnSaturation(); 456 break; 457 case GL_FLOAT_MAT3: 458 EXPECT_CALL(*gl, UniformMatrix3fv( 459 info.real_location, info.size, false, _)) 460 .Times(1) 461 .RetiresOnSaturation(); 462 break; 463 case GL_FLOAT_MAT4: 464 EXPECT_CALL(*gl, UniformMatrix4fv( 465 info.real_location, info.size, false, _)) 466 .Times(1) 467 .RetiresOnSaturation(); 468 break; 469 default: 470 NOTREACHED(); 471 break; 472 } 473 } 474 } 475 476 void TestHelper::SetupProgramSuccessExpectations( 477 ::gfx::MockGLInterface* gl, 478 AttribInfo* attribs, size_t num_attribs, 479 UniformInfo* uniforms, size_t num_uniforms, 480 GLuint service_id) { 481 EXPECT_CALL(*gl, 482 GetProgramiv(service_id, GL_LINK_STATUS, _)) 483 .WillOnce(SetArgumentPointee<2>(1)) 484 .RetiresOnSaturation(); 485 EXPECT_CALL(*gl, 486 GetProgramiv(service_id, GL_INFO_LOG_LENGTH, _)) 487 .WillOnce(SetArgumentPointee<2>(0)) 488 .RetiresOnSaturation(); 489 EXPECT_CALL(*gl, 490 GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _)) 491 .WillOnce(SetArgumentPointee<2>(num_attribs)) 492 .RetiresOnSaturation(); 493 size_t max_attrib_len = 0; 494 for (size_t ii = 0; ii < num_attribs; ++ii) { 495 size_t len = strlen(attribs[ii].name) + 1; 496 max_attrib_len = std::max(max_attrib_len, len); 497 } 498 EXPECT_CALL(*gl, 499 GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _)) 500 .WillOnce(SetArgumentPointee<2>(max_attrib_len)) 501 .RetiresOnSaturation(); 502 503 for (size_t ii = 0; ii < num_attribs; ++ii) { 504 const AttribInfo& info = attribs[ii]; 505 EXPECT_CALL(*gl, 506 GetActiveAttrib(service_id, ii, 507 max_attrib_len, _, _, _, _)) 508 .WillOnce(DoAll( 509 SetArgumentPointee<3>(strlen(info.name)), 510 SetArgumentPointee<4>(info.size), 511 SetArgumentPointee<5>(info.type), 512 SetArrayArgument<6>(info.name, 513 info.name + strlen(info.name) + 1))) 514 .RetiresOnSaturation(); 515 if (!ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) { 516 EXPECT_CALL(*gl, GetAttribLocation(service_id, StrEq(info.name))) 517 .WillOnce(Return(info.location)) 518 .RetiresOnSaturation(); 519 } 520 } 521 EXPECT_CALL(*gl, 522 GetProgramiv(service_id, GL_ACTIVE_UNIFORMS, _)) 523 .WillOnce(SetArgumentPointee<2>(num_uniforms)) 524 .RetiresOnSaturation(); 525 526 size_t max_uniform_len = 0; 527 for (size_t ii = 0; ii < num_uniforms; ++ii) { 528 size_t len = strlen(uniforms[ii].name) + 1; 529 max_uniform_len = std::max(max_uniform_len, len); 530 } 531 EXPECT_CALL(*gl, 532 GetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, _)) 533 .WillOnce(SetArgumentPointee<2>(max_uniform_len)) 534 .RetiresOnSaturation(); 535 for (size_t ii = 0; ii < num_uniforms; ++ii) { 536 const UniformInfo& info = uniforms[ii]; 537 EXPECT_CALL(*gl, 538 GetActiveUniform(service_id, ii, 539 max_uniform_len, _, _, _, _)) 540 .WillOnce(DoAll( 541 SetArgumentPointee<3>(strlen(info.name)), 542 SetArgumentPointee<4>(info.size), 543 SetArgumentPointee<5>(info.type), 544 SetArrayArgument<6>(info.name, 545 info.name + strlen(info.name) + 1))) 546 .RetiresOnSaturation(); 547 } 548 549 for (int pass = 0; pass < 2; ++pass) { 550 for (size_t ii = 0; ii < num_uniforms; ++ii) { 551 const UniformInfo& info = uniforms[ii]; 552 if (ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) { 553 continue; 554 } 555 if (pass == 0) { 556 EXPECT_CALL(*gl, GetUniformLocation(service_id, StrEq(info.name))) 557 .WillOnce(Return(info.real_location)) 558 .RetiresOnSaturation(); 559 } 560 if ((pass == 0 && info.desired_location >= 0) || 561 (pass == 1 && info.desired_location < 0)) { 562 if (info.size > 1) { 563 std::string base_name = info.name; 564 size_t array_pos = base_name.rfind("[0]"); 565 if (base_name.size() > 3 && array_pos == base_name.size() - 3) { 566 base_name = base_name.substr(0, base_name.size() - 3); 567 } 568 for (GLsizei jj = 1; jj < info.size; ++jj) { 569 std::string element_name( 570 std::string(base_name) + "[" + base::IntToString(jj) + "]"); 571 EXPECT_CALL(*gl, GetUniformLocation( 572 service_id, StrEq(element_name))) 573 .WillOnce(Return(info.real_location + jj * 2)) 574 .RetiresOnSaturation(); 575 } 576 } 577 } 578 } 579 } 580 } 581 582 void TestHelper::SetupShader( 583 ::gfx::MockGLInterface* gl, 584 AttribInfo* attribs, size_t num_attribs, 585 UniformInfo* uniforms, size_t num_uniforms, 586 GLuint service_id) { 587 InSequence s; 588 589 EXPECT_CALL(*gl, 590 LinkProgram(service_id)) 591 .Times(1) 592 .RetiresOnSaturation(); 593 594 SetupProgramSuccessExpectations( 595 gl, attribs, num_attribs, uniforms, num_uniforms, service_id); 596 } 597 598 void TestHelper::DoBufferData( 599 ::gfx::MockGLInterface* gl, MockErrorState* error_state, 600 BufferManager* manager, Buffer* buffer, GLsizeiptr size, GLenum usage, 601 const GLvoid* data, GLenum error) { 602 EXPECT_CALL(*error_state, CopyRealGLErrorsToWrapper(_, _, _)) 603 .Times(1) 604 .RetiresOnSaturation(); 605 if (manager->IsUsageClientSideArray(usage)) { 606 EXPECT_CALL(*gl, BufferData( 607 buffer->target(), 0, _, usage)) 608 .Times(1) 609 .RetiresOnSaturation(); 610 } else { 611 EXPECT_CALL(*gl, BufferData( 612 buffer->target(), size, _, usage)) 613 .Times(1) 614 .RetiresOnSaturation(); 615 } 616 EXPECT_CALL(*error_state, PeekGLError(_, _, _)) 617 .WillOnce(Return(error)) 618 .RetiresOnSaturation(); 619 manager->DoBufferData(error_state, buffer, size, usage, data); 620 } 621 622 void TestHelper::SetTexParameteriWithExpectations( 623 ::gfx::MockGLInterface* gl, MockErrorState* error_state, 624 TextureManager* manager, TextureRef* texture_ref, 625 GLenum pname, GLint value, GLenum error) { 626 if (error == GL_NO_ERROR) { 627 if (pname != GL_TEXTURE_POOL_CHROMIUM) { 628 EXPECT_CALL(*gl, TexParameteri(texture_ref->texture()->target(), 629 pname, value)) 630 .Times(1) 631 .RetiresOnSaturation(); 632 } 633 } else if (error == GL_INVALID_ENUM) { 634 EXPECT_CALL(*error_state, SetGLErrorInvalidEnum(_, _, _, value, _)) 635 .Times(1) 636 .RetiresOnSaturation(); 637 } else { 638 EXPECT_CALL(*error_state, SetGLErrorInvalidParami(_, _, error, _, _, _)) 639 .Times(1) 640 .RetiresOnSaturation(); 641 } 642 manager->SetParameteri("", error_state, texture_ref, pname, value); 643 } 644 645 // static 646 void TestHelper::SetShaderStates( 647 ::gfx::MockGLInterface* gl, Shader* shader, 648 bool expected_valid, 649 const std::string* const expected_log_info, 650 const std::string* const expected_translated_source, 651 const ShaderTranslatorInterface::VariableMap* const expected_attrib_map, 652 const ShaderTranslatorInterface::VariableMap* const expected_uniform_map, 653 const ShaderTranslatorInterface::VariableMap* const expected_varying_map, 654 const ShaderTranslatorInterface::NameMap* const expected_name_map) { 655 const std::string empty_log_info; 656 const std::string* log_info = (expected_log_info && !expected_valid) ? 657 expected_log_info : &empty_log_info; 658 const std::string empty_translated_source; 659 const std::string* translated_source = 660 (expected_translated_source && expected_valid) ? 661 expected_translated_source : &empty_translated_source; 662 const ShaderTranslatorInterface::VariableMap empty_attrib_map; 663 const ShaderTranslatorInterface::VariableMap* attrib_map = 664 (expected_attrib_map && expected_valid) ? 665 expected_attrib_map : &empty_attrib_map; 666 const ShaderTranslatorInterface::VariableMap empty_uniform_map; 667 const ShaderTranslatorInterface::VariableMap* uniform_map = 668 (expected_uniform_map && expected_valid) ? 669 expected_uniform_map : &empty_uniform_map; 670 const ShaderTranslatorInterface::VariableMap empty_varying_map; 671 const ShaderTranslatorInterface::VariableMap* varying_map = 672 (expected_varying_map && expected_valid) ? 673 expected_varying_map : &empty_varying_map; 674 const ShaderTranslatorInterface::NameMap empty_name_map; 675 const ShaderTranslatorInterface::NameMap* name_map = 676 (expected_name_map && expected_valid) ? 677 expected_name_map : &empty_name_map; 678 679 MockShaderTranslator translator; 680 EXPECT_CALL(translator, Translate(_, 681 NotNull(), // log_info 682 NotNull(), // translated_source 683 NotNull(), // attrib_map 684 NotNull(), // uniform_map 685 NotNull(), // varying_map 686 NotNull())) // name_map 687 .WillOnce(DoAll(SetArgumentPointee<1>(*log_info), 688 SetArgumentPointee<2>(*translated_source), 689 SetArgumentPointee<3>(*attrib_map), 690 SetArgumentPointee<4>(*uniform_map), 691 SetArgumentPointee<5>(*varying_map), 692 SetArgumentPointee<6>(*name_map), 693 Return(expected_valid))) 694 .RetiresOnSaturation(); 695 if (expected_valid) { 696 EXPECT_CALL(*gl, ShaderSource(shader->service_id(), 1, _, NULL)) 697 .Times(1) 698 .RetiresOnSaturation(); 699 EXPECT_CALL(*gl, CompileShader(shader->service_id())) 700 .Times(1) 701 .RetiresOnSaturation(); 702 EXPECT_CALL(*gl, GetShaderiv(shader->service_id(), 703 GL_COMPILE_STATUS, 704 NotNull())) // status 705 .WillOnce(SetArgumentPointee<2>(GL_TRUE)) 706 .RetiresOnSaturation(); 707 } 708 shader->DoCompile(&translator, Shader::kGL); 709 } 710 711 // static 712 void TestHelper::SetShaderStates( 713 ::gfx::MockGLInterface* gl, Shader* shader, bool valid) { 714 SetShaderStates(gl, shader, valid, NULL, NULL, NULL, NULL, NULL, NULL); 715 } 716 717 ScopedGLImplementationSetter::ScopedGLImplementationSetter( 718 gfx::GLImplementation implementation) 719 : old_implementation_(gfx::GetGLImplementation()) { 720 gfx::SetGLImplementation(implementation); 721 } 722 723 ScopedGLImplementationSetter::~ScopedGLImplementationSetter() { 724 gfx::SetGLImplementation(old_implementation_); 725 } 726 727 } // namespace gles2 728 } // namespace gpu 729 730