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/program_manager.h" 6 7 #include <algorithm> 8 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_util.h" 12 #include "gpu/command_buffer/common/gles2_cmd_format.h" 13 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 14 #include "gpu/command_buffer/service/common_decoder.h" 15 #include "gpu/command_buffer/service/feature_info.h" 16 #include "gpu/command_buffer/service/gpu_service_test.h" 17 #include "gpu/command_buffer/service/mocks.h" 18 #include "gpu/command_buffer/service/shader_manager.h" 19 #include "gpu/command_buffer/service/test_helper.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "ui/gl/gl_mock.h" 22 23 using ::testing::_; 24 using ::testing::DoAll; 25 using ::testing::InSequence; 26 using ::testing::MatcherCast; 27 using ::testing::Pointee; 28 using ::testing::Return; 29 using ::testing::ReturnRef; 30 using ::testing::SetArrayArgument; 31 using ::testing::SetArgumentPointee; 32 using ::testing::StrEq; 33 34 namespace gpu { 35 namespace gles2 { 36 37 namespace { 38 const uint32 kMaxVaryingVectors = 8; 39 40 void ShaderCacheCb(const std::string& key, const std::string& shader) {} 41 } // namespace anonymous 42 43 class ProgramManagerTest : public GpuServiceTest { 44 public: 45 ProgramManagerTest() : manager_(NULL, kMaxVaryingVectors) { } 46 virtual ~ProgramManagerTest() { 47 manager_.Destroy(false); 48 } 49 50 protected: 51 ProgramManager manager_; 52 }; 53 54 TEST_F(ProgramManagerTest, Basic) { 55 const GLuint kClient1Id = 1; 56 const GLuint kService1Id = 11; 57 const GLuint kClient2Id = 2; 58 // Check we can create program. 59 manager_.CreateProgram(kClient1Id, kService1Id); 60 // Check program got created. 61 Program* program1 = manager_.GetProgram(kClient1Id); 62 ASSERT_TRUE(program1 != NULL); 63 GLuint client_id = 0; 64 EXPECT_TRUE(manager_.GetClientId(program1->service_id(), &client_id)); 65 EXPECT_EQ(kClient1Id, client_id); 66 // Check we get nothing for a non-existent program. 67 EXPECT_TRUE(manager_.GetProgram(kClient2Id) == NULL); 68 } 69 70 TEST_F(ProgramManagerTest, Destroy) { 71 const GLuint kClient1Id = 1; 72 const GLuint kService1Id = 11; 73 // Check we can create program. 74 Program* program0 = manager_.CreateProgram(kClient1Id, kService1Id); 75 ASSERT_TRUE(program0 != NULL); 76 // Check program got created. 77 Program* program1 = manager_.GetProgram(kClient1Id); 78 ASSERT_EQ(program0, program1); 79 EXPECT_CALL(*gl_, DeleteProgram(kService1Id)) 80 .Times(1) 81 .RetiresOnSaturation(); 82 manager_.Destroy(true); 83 // Check the resources were released. 84 program1 = manager_.GetProgram(kClient1Id); 85 ASSERT_TRUE(program1 == NULL); 86 } 87 88 TEST_F(ProgramManagerTest, DeleteBug) { 89 ShaderManager shader_manager; 90 const GLuint kClient1Id = 1; 91 const GLuint kClient2Id = 2; 92 const GLuint kService1Id = 11; 93 const GLuint kService2Id = 12; 94 // Check we can create program. 95 scoped_refptr<Program> program1( 96 manager_.CreateProgram(kClient1Id, kService1Id)); 97 scoped_refptr<Program> program2( 98 manager_.CreateProgram(kClient2Id, kService2Id)); 99 // Check program got created. 100 ASSERT_TRUE(program1.get()); 101 ASSERT_TRUE(program2.get()); 102 manager_.UseProgram(program1.get()); 103 manager_.MarkAsDeleted(&shader_manager, program1.get()); 104 // Program will be deleted when last ref is released. 105 EXPECT_CALL(*gl_, DeleteProgram(kService2Id)) 106 .Times(1) 107 .RetiresOnSaturation(); 108 manager_.MarkAsDeleted(&shader_manager, program2.get()); 109 EXPECT_TRUE(manager_.IsOwned(program1.get())); 110 EXPECT_FALSE(manager_.IsOwned(program2.get())); 111 } 112 113 TEST_F(ProgramManagerTest, Program) { 114 const GLuint kClient1Id = 1; 115 const GLuint kService1Id = 11; 116 // Check we can create program. 117 Program* program1 = manager_.CreateProgram( 118 kClient1Id, kService1Id); 119 ASSERT_TRUE(program1); 120 EXPECT_EQ(kService1Id, program1->service_id()); 121 EXPECT_FALSE(program1->InUse()); 122 EXPECT_FALSE(program1->IsValid()); 123 EXPECT_FALSE(program1->IsDeleted()); 124 EXPECT_FALSE(program1->CanLink()); 125 EXPECT_TRUE(program1->log_info() == NULL); 126 } 127 128 class ProgramManagerWithShaderTest : public GpuServiceTest { 129 public: 130 ProgramManagerWithShaderTest() 131 : manager_(NULL, kMaxVaryingVectors), program_(NULL) { 132 } 133 134 virtual ~ProgramManagerWithShaderTest() { 135 manager_.Destroy(false); 136 shader_manager_.Destroy(false); 137 } 138 139 static const GLint kNumVertexAttribs = 16; 140 141 static const GLuint kClientProgramId = 123; 142 static const GLuint kServiceProgramId = 456; 143 static const GLuint kVertexShaderClientId = 201; 144 static const GLuint kFragmentShaderClientId = 202; 145 static const GLuint kVertexShaderServiceId = 301; 146 static const GLuint kFragmentShaderServiceId = 302; 147 148 static const char* kAttrib1Name; 149 static const char* kAttrib2Name; 150 static const char* kAttrib3Name; 151 static const GLint kAttrib1Size = 1; 152 static const GLint kAttrib2Size = 1; 153 static const GLint kAttrib3Size = 1; 154 static const int kAttrib1Precision = SH_PRECISION_MEDIUMP; 155 static const int kAttrib2Precision = SH_PRECISION_HIGHP; 156 static const int kAttrib3Precision = SH_PRECISION_LOWP; 157 static const int kAttribStaticUse = 0; 158 static const GLint kAttrib1Location = 0; 159 static const GLint kAttrib2Location = 1; 160 static const GLint kAttrib3Location = 2; 161 static const GLenum kAttrib1Type = GL_FLOAT_VEC4; 162 static const GLenum kAttrib2Type = GL_FLOAT_VEC2; 163 static const GLenum kAttrib3Type = GL_FLOAT_VEC3; 164 static const GLint kInvalidAttribLocation = 30; 165 static const GLint kBadAttribIndex = kNumVertexAttribs; 166 167 static const char* kUniform1Name; 168 static const char* kUniform2Name; 169 static const char* kUniform3BadName; 170 static const char* kUniform3GoodName; 171 static const GLint kUniform1Size = 1; 172 static const GLint kUniform2Size = 3; 173 static const GLint kUniform3Size = 2; 174 static const int kUniform1Precision = SH_PRECISION_LOWP; 175 static const int kUniform2Precision = SH_PRECISION_MEDIUMP; 176 static const int kUniform3Precision = SH_PRECISION_HIGHP; 177 static const int kUniform1StaticUse = 1; 178 static const int kUniform2StaticUse = 1; 179 static const int kUniform3StaticUse = 1; 180 static const GLint kUniform1FakeLocation = 0; // These are hard coded 181 static const GLint kUniform2FakeLocation = 1; // to match 182 static const GLint kUniform3FakeLocation = 2; // ProgramManager. 183 static const GLint kUniform1RealLocation = 11; 184 static const GLint kUniform2RealLocation = 22; 185 static const GLint kUniform3RealLocation = 33; 186 static const GLint kUniform1DesiredLocation = -1; 187 static const GLint kUniform2DesiredLocation = -1; 188 static const GLint kUniform3DesiredLocation = -1; 189 static const GLenum kUniform1Type = GL_FLOAT_VEC4; 190 static const GLenum kUniform2Type = GL_INT_VEC2; 191 static const GLenum kUniform3Type = GL_FLOAT_VEC3; 192 static const GLint kInvalidUniformLocation = 30; 193 static const GLint kBadUniformIndex = 1000; 194 195 static const size_t kNumAttribs; 196 static const size_t kNumUniforms; 197 198 protected: 199 typedef TestHelper::AttribInfo AttribInfo; 200 typedef TestHelper::UniformInfo UniformInfo; 201 202 typedef enum { 203 kVarUniform, 204 kVarVarying, 205 kVarAttribute 206 } VarCategory; 207 208 typedef struct { 209 int type; 210 int size; 211 int precision; 212 int static_use; 213 std::string name; 214 VarCategory category; 215 } VarInfo; 216 217 virtual void SetUp() { 218 GpuServiceTest::SetUp(); 219 220 SetupDefaultShaderExpectations(); 221 222 Shader* vertex_shader = shader_manager_.CreateShader( 223 kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER); 224 Shader* fragment_shader = 225 shader_manager_.CreateShader( 226 kFragmentShaderClientId, kFragmentShaderServiceId, 227 GL_FRAGMENT_SHADER); 228 ASSERT_TRUE(vertex_shader != NULL); 229 ASSERT_TRUE(fragment_shader != NULL); 230 TestHelper::SetShaderStates(gl_.get(), vertex_shader, true); 231 TestHelper::SetShaderStates(gl_.get(), fragment_shader, true); 232 233 program_ = manager_.CreateProgram( 234 kClientProgramId, kServiceProgramId); 235 ASSERT_TRUE(program_ != NULL); 236 237 program_->AttachShader(&shader_manager_, vertex_shader); 238 program_->AttachShader(&shader_manager_, fragment_shader); 239 program_->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed, 240 base::Bind(&ShaderCacheCb)); 241 } 242 243 void SetupShader(AttribInfo* attribs, size_t num_attribs, 244 UniformInfo* uniforms, size_t num_uniforms, 245 GLuint service_id) { 246 TestHelper::SetupShader( 247 gl_.get(), attribs, num_attribs, uniforms, num_uniforms, service_id); 248 } 249 250 void SetupDefaultShaderExpectations() { 251 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 252 kServiceProgramId); 253 } 254 255 void SetupExpectationsForClearingUniforms( 256 UniformInfo* uniforms, size_t num_uniforms) { 257 TestHelper::SetupExpectationsForClearingUniforms( 258 gl_.get(), uniforms, num_uniforms); 259 } 260 261 // Return true if link status matches expected_link_status 262 bool LinkAsExpected(Program* program, 263 bool expected_link_status) { 264 GLuint service_id = program->service_id(); 265 if (expected_link_status) { 266 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 267 service_id); 268 } 269 program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed, 270 base::Bind(&ShaderCacheCb)); 271 GLint link_status; 272 program->GetProgramiv(GL_LINK_STATUS, &link_status); 273 return (static_cast<bool>(link_status) == expected_link_status); 274 } 275 276 Program* SetupShaderVariableTest(const VarInfo* vertex_variables, 277 size_t vertex_variable_size, 278 const VarInfo* fragment_variables, 279 size_t fragment_variable_size) { 280 // Set up shader 281 const GLuint kVShaderClientId = 1; 282 const GLuint kVShaderServiceId = 11; 283 const GLuint kFShaderClientId = 2; 284 const GLuint kFShaderServiceId = 12; 285 286 ShaderTranslator::VariableMap vertex_attrib_map; 287 ShaderTranslator::VariableMap vertex_uniform_map; 288 ShaderTranslator::VariableMap vertex_varying_map; 289 for (size_t ii = 0; ii < vertex_variable_size; ++ii) { 290 ShaderTranslator::VariableMap* map = NULL; 291 switch (vertex_variables[ii].category) { 292 case kVarAttribute: 293 map = &vertex_attrib_map; 294 break; 295 case kVarUniform: 296 map = &vertex_uniform_map; 297 break; 298 case kVarVarying: 299 map = &vertex_varying_map; 300 break; 301 default: 302 NOTREACHED(); 303 } 304 (*map)[vertex_variables[ii].name] = 305 ShaderTranslator::VariableInfo(vertex_variables[ii].type, 306 vertex_variables[ii].size, 307 vertex_variables[ii].precision, 308 vertex_variables[ii].static_use, 309 vertex_variables[ii].name); 310 } 311 312 ShaderTranslator::VariableMap frag_attrib_map; 313 ShaderTranslator::VariableMap frag_uniform_map; 314 ShaderTranslator::VariableMap frag_varying_map; 315 for (size_t ii = 0; ii < fragment_variable_size; ++ii) { 316 ShaderTranslator::VariableMap* map = NULL; 317 switch (fragment_variables[ii].category) { 318 case kVarAttribute: 319 map = &frag_attrib_map; 320 break; 321 case kVarUniform: 322 map = &frag_uniform_map; 323 break; 324 case kVarVarying: 325 map = &frag_varying_map; 326 break; 327 default: 328 NOTREACHED(); 329 } 330 (*map)[fragment_variables[ii].name] = 331 ShaderTranslator::VariableInfo(fragment_variables[ii].type, 332 fragment_variables[ii].size, 333 fragment_variables[ii].precision, 334 fragment_variables[ii].static_use, 335 fragment_variables[ii].name); 336 } 337 338 // Check we can create shader. 339 Shader* vshader = shader_manager_.CreateShader( 340 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 341 Shader* fshader = shader_manager_.CreateShader( 342 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 343 // Check shader got created. 344 EXPECT_TRUE(vshader != NULL && fshader != NULL); 345 // Set Status 346 TestHelper::SetShaderStates( 347 gl_.get(), vshader, true, NULL, NULL, 348 &vertex_attrib_map, &vertex_uniform_map, &vertex_varying_map, NULL); 349 TestHelper::SetShaderStates( 350 gl_.get(), fshader, true, NULL, NULL, 351 &frag_attrib_map, &frag_uniform_map, &frag_varying_map, NULL); 352 353 // Set up program 354 const GLuint kClientProgramId = 6666; 355 const GLuint kServiceProgramId = 8888; 356 Program* program = 357 manager_.CreateProgram(kClientProgramId, kServiceProgramId); 358 EXPECT_TRUE(program != NULL); 359 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 360 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 361 return program; 362 } 363 364 static AttribInfo kAttribs[]; 365 static UniformInfo kUniforms[]; 366 367 ProgramManager manager_; 368 Program* program_; 369 ShaderManager shader_manager_; 370 }; 371 372 ProgramManagerWithShaderTest::AttribInfo 373 ProgramManagerWithShaderTest::kAttribs[] = { 374 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, 375 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, 376 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, 377 }; 378 379 // GCC requires these declarations, but MSVC requires they not be present 380 #ifndef COMPILER_MSVC 381 const GLint ProgramManagerWithShaderTest::kNumVertexAttribs; 382 const GLuint ProgramManagerWithShaderTest::kClientProgramId; 383 const GLuint ProgramManagerWithShaderTest::kServiceProgramId; 384 const GLuint ProgramManagerWithShaderTest::kVertexShaderClientId; 385 const GLuint ProgramManagerWithShaderTest::kFragmentShaderClientId; 386 const GLuint ProgramManagerWithShaderTest::kVertexShaderServiceId; 387 const GLuint ProgramManagerWithShaderTest::kFragmentShaderServiceId; 388 const GLint ProgramManagerWithShaderTest::kAttrib1Size; 389 const GLint ProgramManagerWithShaderTest::kAttrib2Size; 390 const GLint ProgramManagerWithShaderTest::kAttrib3Size; 391 const GLint ProgramManagerWithShaderTest::kAttrib1Location; 392 const GLint ProgramManagerWithShaderTest::kAttrib2Location; 393 const GLint ProgramManagerWithShaderTest::kAttrib3Location; 394 const GLenum ProgramManagerWithShaderTest::kAttrib1Type; 395 const GLenum ProgramManagerWithShaderTest::kAttrib2Type; 396 const GLenum ProgramManagerWithShaderTest::kAttrib3Type; 397 const GLint ProgramManagerWithShaderTest::kInvalidAttribLocation; 398 const GLint ProgramManagerWithShaderTest::kBadAttribIndex; 399 const GLint ProgramManagerWithShaderTest::kUniform1Size; 400 const GLint ProgramManagerWithShaderTest::kUniform2Size; 401 const GLint ProgramManagerWithShaderTest::kUniform3Size; 402 const GLint ProgramManagerWithShaderTest::kUniform1FakeLocation; 403 const GLint ProgramManagerWithShaderTest::kUniform2FakeLocation; 404 const GLint ProgramManagerWithShaderTest::kUniform3FakeLocation; 405 const GLint ProgramManagerWithShaderTest::kUniform1RealLocation; 406 const GLint ProgramManagerWithShaderTest::kUniform2RealLocation; 407 const GLint ProgramManagerWithShaderTest::kUniform3RealLocation; 408 const GLint ProgramManagerWithShaderTest::kUniform1DesiredLocation; 409 const GLint ProgramManagerWithShaderTest::kUniform2DesiredLocation; 410 const GLint ProgramManagerWithShaderTest::kUniform3DesiredLocation; 411 const GLenum ProgramManagerWithShaderTest::kUniform1Type; 412 const GLenum ProgramManagerWithShaderTest::kUniform2Type; 413 const GLenum ProgramManagerWithShaderTest::kUniform3Type; 414 const GLint ProgramManagerWithShaderTest::kInvalidUniformLocation; 415 const GLint ProgramManagerWithShaderTest::kBadUniformIndex; 416 #endif 417 418 const size_t ProgramManagerWithShaderTest::kNumAttribs = 419 arraysize(ProgramManagerWithShaderTest::kAttribs); 420 421 ProgramManagerWithShaderTest::UniformInfo 422 ProgramManagerWithShaderTest::kUniforms[] = { 423 { kUniform1Name, 424 kUniform1Size, 425 kUniform1Type, 426 kUniform1FakeLocation, 427 kUniform1RealLocation, 428 kUniform1DesiredLocation, 429 kUniform1Name, 430 }, 431 { kUniform2Name, 432 kUniform2Size, 433 kUniform2Type, 434 kUniform2FakeLocation, 435 kUniform2RealLocation, 436 kUniform2DesiredLocation, 437 kUniform2Name, 438 }, 439 { kUniform3BadName, 440 kUniform3Size, 441 kUniform3Type, 442 kUniform3FakeLocation, 443 kUniform3RealLocation, 444 kUniform3DesiredLocation, 445 kUniform3GoodName, 446 }, 447 }; 448 449 const size_t ProgramManagerWithShaderTest::kNumUniforms = 450 arraysize(ProgramManagerWithShaderTest::kUniforms); 451 452 const char* ProgramManagerWithShaderTest::kAttrib1Name = "attrib1"; 453 const char* ProgramManagerWithShaderTest::kAttrib2Name = "attrib2"; 454 const char* ProgramManagerWithShaderTest::kAttrib3Name = "attrib3"; 455 const char* ProgramManagerWithShaderTest::kUniform1Name = "uniform1"; 456 // Correctly has array spec. 457 const char* ProgramManagerWithShaderTest::kUniform2Name = "uniform2[0]"; 458 // Incorrectly missing array spec. 459 const char* ProgramManagerWithShaderTest::kUniform3BadName = "uniform3"; 460 const char* ProgramManagerWithShaderTest::kUniform3GoodName = "uniform3[0]"; 461 462 TEST_F(ProgramManagerWithShaderTest, GetAttribInfos) { 463 const Program* program = manager_.GetProgram(kClientProgramId); 464 ASSERT_TRUE(program != NULL); 465 const Program::AttribInfoVector& infos = 466 program->GetAttribInfos(); 467 ASSERT_EQ(kNumAttribs, infos.size()); 468 for (size_t ii = 0; ii < kNumAttribs; ++ii) { 469 const Program::VertexAttrib& info = infos[ii]; 470 const AttribInfo& expected = kAttribs[ii]; 471 EXPECT_EQ(expected.size, info.size); 472 EXPECT_EQ(expected.type, info.type); 473 EXPECT_EQ(expected.location, info.location); 474 EXPECT_STREQ(expected.name, info.name.c_str()); 475 } 476 } 477 478 TEST_F(ProgramManagerWithShaderTest, GetAttribInfo) { 479 const GLint kValidIndex = 1; 480 const GLint kInvalidIndex = 1000; 481 const Program* program = manager_.GetProgram(kClientProgramId); 482 ASSERT_TRUE(program != NULL); 483 const Program::VertexAttrib* info = 484 program->GetAttribInfo(kValidIndex); 485 ASSERT_TRUE(info != NULL); 486 EXPECT_EQ(kAttrib2Size, info->size); 487 EXPECT_EQ(kAttrib2Type, info->type); 488 EXPECT_EQ(kAttrib2Location, info->location); 489 EXPECT_STREQ(kAttrib2Name, info->name.c_str()); 490 EXPECT_TRUE(program->GetAttribInfo(kInvalidIndex) == NULL); 491 } 492 493 TEST_F(ProgramManagerWithShaderTest, GetAttribLocation) { 494 const char* kInvalidName = "foo"; 495 const Program* program = manager_.GetProgram(kClientProgramId); 496 ASSERT_TRUE(program != NULL); 497 EXPECT_EQ(kAttrib2Location, program->GetAttribLocation(kAttrib2Name)); 498 EXPECT_EQ(-1, program->GetAttribLocation(kInvalidName)); 499 } 500 501 TEST_F(ProgramManagerWithShaderTest, GetUniformInfo) { 502 const GLint kInvalidIndex = 1000; 503 const Program* program = manager_.GetProgram(kClientProgramId); 504 ASSERT_TRUE(program != NULL); 505 const Program::UniformInfo* info = 506 program->GetUniformInfo(0); 507 ASSERT_TRUE(info != NULL); 508 EXPECT_EQ(kUniform1Size, info->size); 509 EXPECT_EQ(kUniform1Type, info->type); 510 EXPECT_EQ(kUniform1RealLocation, info->element_locations[0]); 511 EXPECT_STREQ(kUniform1Name, info->name.c_str()); 512 info = program->GetUniformInfo(1); 513 ASSERT_TRUE(info != NULL); 514 EXPECT_EQ(kUniform2Size, info->size); 515 EXPECT_EQ(kUniform2Type, info->type); 516 EXPECT_EQ(kUniform2RealLocation, info->element_locations[0]); 517 EXPECT_STREQ(kUniform2Name, info->name.c_str()); 518 info = program->GetUniformInfo(2); 519 // We emulate certain OpenGL drivers by supplying the name without 520 // the array spec. Our implementation should correctly add the required spec. 521 ASSERT_TRUE(info != NULL); 522 EXPECT_EQ(kUniform3Size, info->size); 523 EXPECT_EQ(kUniform3Type, info->type); 524 EXPECT_EQ(kUniform3RealLocation, info->element_locations[0]); 525 EXPECT_STREQ(kUniform3GoodName, info->name.c_str()); 526 EXPECT_TRUE(program->GetUniformInfo(kInvalidIndex) == NULL); 527 } 528 529 TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) { 530 static const GLuint kClientProgramId = 124; 531 static const GLuint kServiceProgramId = 457; 532 Program* program = manager_.CreateProgram( 533 kClientProgramId, kServiceProgramId); 534 ASSERT_TRUE(program != NULL); 535 EXPECT_FALSE(program->CanLink()); 536 const GLuint kVShaderClientId = 2001; 537 const GLuint kFShaderClientId = 2002; 538 const GLuint kVShaderServiceId = 3001; 539 const GLuint kFShaderServiceId = 3002; 540 Shader* vshader = shader_manager_.CreateShader( 541 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 542 ASSERT_TRUE(vshader != NULL); 543 TestHelper::SetShaderStates(gl_.get(), vshader, true); 544 Shader* fshader = shader_manager_.CreateShader( 545 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 546 ASSERT_TRUE(fshader != NULL); 547 TestHelper::SetShaderStates(gl_.get(), fshader, true); 548 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 549 EXPECT_FALSE(program->CanLink()); 550 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 551 EXPECT_TRUE(program->CanLink()); 552 program->DetachShader(&shader_manager_, vshader); 553 EXPECT_FALSE(program->CanLink()); 554 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 555 EXPECT_TRUE(program->CanLink()); 556 program->DetachShader(&shader_manager_, fshader); 557 EXPECT_FALSE(program->CanLink()); 558 EXPECT_FALSE(program->AttachShader(&shader_manager_, vshader)); 559 EXPECT_FALSE(program->CanLink()); 560 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 561 EXPECT_TRUE(program->CanLink()); 562 TestHelper::SetShaderStates(gl_.get(), vshader, false); 563 EXPECT_FALSE(program->CanLink()); 564 TestHelper::SetShaderStates(gl_.get(), vshader, true); 565 EXPECT_TRUE(program->CanLink()); 566 TestHelper::SetShaderStates(gl_.get(), fshader, false); 567 EXPECT_FALSE(program->CanLink()); 568 TestHelper::SetShaderStates(gl_.get(), fshader, true); 569 EXPECT_TRUE(program->CanLink()); 570 EXPECT_TRUE(program->DetachShader(&shader_manager_, fshader)); 571 EXPECT_FALSE(program->DetachShader(&shader_manager_, fshader)); 572 } 573 574 TEST_F(ProgramManagerWithShaderTest, GetUniformFakeLocation) { 575 const Program* program = manager_.GetProgram(kClientProgramId); 576 ASSERT_TRUE(program != NULL); 577 // Emulate the situation that uniform3[1] isn't used and optimized out by 578 // a driver, so it's location is -1. 579 Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>( 580 program->GetUniformInfo(2)); 581 ASSERT_TRUE(uniform != NULL && kUniform3Size == 2); 582 EXPECT_EQ(kUniform3Size, uniform->size); 583 uniform->element_locations[1] = -1; 584 EXPECT_EQ(kUniform1FakeLocation, 585 program->GetUniformFakeLocation(kUniform1Name)); 586 EXPECT_EQ(kUniform2FakeLocation, 587 program->GetUniformFakeLocation(kUniform2Name)); 588 EXPECT_EQ(kUniform3FakeLocation, 589 program->GetUniformFakeLocation(kUniform3BadName)); 590 // Check we can get uniform2 as "uniform2" even though the name is 591 // "uniform2[0]" 592 EXPECT_EQ(kUniform2FakeLocation, 593 program->GetUniformFakeLocation("uniform2")); 594 // Check we can get uniform3 as "uniform3[0]" even though we simulated GL 595 // returning "uniform3" 596 EXPECT_EQ(kUniform3FakeLocation, 597 program->GetUniformFakeLocation(kUniform3GoodName)); 598 // Check that we can get the locations of the array elements > 1 599 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation, 1), 600 program->GetUniformFakeLocation("uniform2[1]")); 601 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation, 2), 602 program->GetUniformFakeLocation("uniform2[2]")); 603 EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform2[3]")); 604 EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform3[1]")); 605 EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform3[2]")); 606 } 607 608 TEST_F(ProgramManagerWithShaderTest, GetUniformInfoByFakeLocation) { 609 const GLint kInvalidLocation = 1234; 610 const Program::UniformInfo* info; 611 const Program* program = manager_.GetProgram(kClientProgramId); 612 GLint real_location = -1; 613 GLint array_index = -1; 614 ASSERT_TRUE(program != NULL); 615 info = program->GetUniformInfoByFakeLocation( 616 kUniform2FakeLocation, &real_location, &array_index); 617 EXPECT_EQ(kUniform2RealLocation, real_location); 618 EXPECT_EQ(0, array_index); 619 ASSERT_TRUE(info != NULL); 620 EXPECT_EQ(kUniform2Type, info->type); 621 real_location = -1; 622 array_index = -1; 623 info = program->GetUniformInfoByFakeLocation( 624 kInvalidLocation, &real_location, &array_index); 625 EXPECT_TRUE(info == NULL); 626 EXPECT_EQ(-1, real_location); 627 EXPECT_EQ(-1, array_index); 628 GLint loc = program->GetUniformFakeLocation("uniform2[2]"); 629 info = program->GetUniformInfoByFakeLocation( 630 loc, &real_location, &array_index); 631 ASSERT_TRUE(info != NULL); 632 EXPECT_EQ(kUniform2RealLocation + 2 * 2, real_location); 633 EXPECT_EQ(2, array_index); 634 } 635 636 // Some GL drivers incorrectly return gl_DepthRange and possibly other uniforms 637 // that start with "gl_". Our implementation catches these and does not allow 638 // them back to client. 639 TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) { 640 static const char* kUniform2Name = "gl_longNameWeCanCheckFor"; 641 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 642 { kUniform1Name, 643 kUniform1Size, 644 kUniform1Type, 645 kUniform1FakeLocation, 646 kUniform1RealLocation, 647 kUniform1DesiredLocation, 648 kUniform1Name, 649 }, 650 { kUniform2Name, 651 kUniform2Size, 652 kUniform2Type, 653 kUniform2FakeLocation, 654 kUniform2RealLocation, 655 kUniform2DesiredLocation, 656 kUniform2Name, 657 }, 658 { kUniform3BadName, 659 kUniform3Size, 660 kUniform3Type, 661 kUniform3FakeLocation, 662 kUniform3RealLocation, 663 kUniform3DesiredLocation, 664 kUniform3GoodName, 665 }, 666 }; 667 const size_t kNumUniforms = arraysize(kUniforms); 668 static const GLuint kClientProgramId = 1234; 669 static const GLuint kServiceProgramId = 5679; 670 const GLuint kVShaderClientId = 2001; 671 const GLuint kFShaderClientId = 2002; 672 const GLuint kVShaderServiceId = 3001; 673 const GLuint kFShaderServiceId = 3002; 674 SetupShader( 675 kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId); 676 Shader* vshader = shader_manager_.CreateShader( 677 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 678 ASSERT_TRUE(vshader != NULL); 679 TestHelper::SetShaderStates(gl_.get(), vshader, true); 680 Shader* fshader = shader_manager_.CreateShader( 681 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 682 ASSERT_TRUE(fshader != NULL); 683 TestHelper::SetShaderStates(gl_.get(), fshader, true); 684 Program* program = 685 manager_.CreateProgram(kClientProgramId, kServiceProgramId); 686 ASSERT_TRUE(program != NULL); 687 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 688 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 689 program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed, 690 base::Bind(&ShaderCacheCb)); 691 GLint value = 0; 692 program->GetProgramiv(GL_ACTIVE_ATTRIBUTES, &value); 693 EXPECT_EQ(3, value); 694 // Check that we skipped the "gl_" uniform. 695 program->GetProgramiv(GL_ACTIVE_UNIFORMS, &value); 696 EXPECT_EQ(2, value); 697 // Check that our max length adds room for the array spec and is not as long 698 // as the "gl_" uniform we skipped. 699 // +4u is to account for "gl_" and NULL terminator. 700 program->GetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH, &value); 701 EXPECT_EQ(strlen(kUniform3BadName) + 4u, static_cast<size_t>(value)); 702 } 703 704 // Test the bug comparing similar array names is fixed. 705 TEST_F(ProgramManagerWithShaderTest, SimilarArrayNames) { 706 static const char* kUniform2Name = "u_nameLong[0]"; 707 static const char* kUniform3Name = "u_name[0]"; 708 static const GLint kUniform2Size = 2; 709 static const GLint kUniform3Size = 2; 710 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 711 { kUniform1Name, 712 kUniform1Size, 713 kUniform1Type, 714 kUniform1FakeLocation, 715 kUniform1RealLocation, 716 kUniform1DesiredLocation, 717 kUniform1Name, 718 }, 719 { kUniform2Name, 720 kUniform2Size, 721 kUniform2Type, 722 kUniform2FakeLocation, 723 kUniform2RealLocation, 724 kUniform2DesiredLocation, 725 kUniform2Name, 726 }, 727 { kUniform3Name, 728 kUniform3Size, 729 kUniform3Type, 730 kUniform3FakeLocation, 731 kUniform3RealLocation, 732 kUniform3DesiredLocation, 733 kUniform3Name, 734 }, 735 }; 736 const size_t kNumUniforms = arraysize(kUniforms); 737 static const GLuint kClientProgramId = 1234; 738 static const GLuint kServiceProgramId = 5679; 739 const GLuint kVShaderClientId = 2001; 740 const GLuint kFShaderClientId = 2002; 741 const GLuint kVShaderServiceId = 3001; 742 const GLuint kFShaderServiceId = 3002; 743 SetupShader( 744 kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId); 745 Shader* vshader = shader_manager_.CreateShader( 746 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 747 ASSERT_TRUE(vshader != NULL); 748 TestHelper::SetShaderStates(gl_.get(), vshader, true); 749 Shader* fshader = shader_manager_.CreateShader( 750 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 751 ASSERT_TRUE(fshader != NULL); 752 TestHelper::SetShaderStates(gl_.get(), fshader, true); 753 Program* program = 754 manager_.CreateProgram(kClientProgramId, kServiceProgramId); 755 ASSERT_TRUE(program != NULL); 756 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 757 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 758 program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed, 759 base::Bind(&ShaderCacheCb)); 760 761 // Check that we get the correct locations. 762 EXPECT_EQ(kUniform2FakeLocation, 763 program->GetUniformFakeLocation(kUniform2Name)); 764 EXPECT_EQ(kUniform3FakeLocation, 765 program->GetUniformFakeLocation(kUniform3Name)); 766 } 767 768 // Some GL drivers incorrectly return the wrong type. For example they return 769 // GL_FLOAT_VEC2 when they should return GL_FLOAT_MAT2. Check we handle this. 770 TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) { 771 static GLenum kAttrib2BadType = GL_FLOAT_VEC2; 772 static GLenum kAttrib2GoodType = GL_FLOAT_MAT2; 773 static GLenum kUniform2BadType = GL_FLOAT_VEC3; 774 static GLenum kUniform2GoodType = GL_FLOAT_MAT3; 775 ShaderTranslator::VariableMap attrib_map; 776 ShaderTranslator::VariableMap uniform_map; 777 ShaderTranslator::VariableMap varying_map; 778 attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo( 779 kAttrib1Type, kAttrib1Size, kAttrib1Precision, 780 kAttribStaticUse, kAttrib1Name); 781 attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo( 782 kAttrib2GoodType, kAttrib2Size, kAttrib2Precision, 783 kAttribStaticUse, kAttrib2Name); 784 attrib_map[kAttrib3Name] = ShaderTranslatorInterface::VariableInfo( 785 kAttrib3Type, kAttrib3Size, kAttrib3Precision, 786 kAttribStaticUse, kAttrib3Name); 787 uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo( 788 kUniform1Type, kUniform1Size, kUniform1Precision, 789 kUniform1StaticUse, kUniform1Name); 790 uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo( 791 kUniform2GoodType, kUniform2Size, kUniform2Precision, 792 kUniform2StaticUse, kUniform2Name); 793 uniform_map[kUniform3GoodName] = ShaderTranslatorInterface::VariableInfo( 794 kUniform3Type, kUniform3Size, kUniform3Precision, 795 kUniform3StaticUse, kUniform3GoodName); 796 const GLuint kVShaderClientId = 2001; 797 const GLuint kFShaderClientId = 2002; 798 const GLuint kVShaderServiceId = 3001; 799 const GLuint kFShaderServiceId = 3002; 800 Shader* vshader = shader_manager_.CreateShader( 801 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 802 ASSERT_TRUE(vshader != NULL); 803 TestHelper::SetShaderStates( 804 gl_.get(), vshader, true, NULL, NULL, 805 &attrib_map, &uniform_map, &varying_map, NULL); 806 Shader* fshader = shader_manager_.CreateShader( 807 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 808 ASSERT_TRUE(fshader != NULL); 809 TestHelper::SetShaderStates( 810 gl_.get(), fshader, true, NULL, NULL, 811 &attrib_map, &uniform_map, &varying_map, NULL); 812 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = { 813 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, 814 { kAttrib2Name, kAttrib2Size, kAttrib2BadType, kAttrib2Location, }, 815 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, 816 }; 817 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 818 { kUniform1Name, 819 kUniform1Size, 820 kUniform1Type, 821 kUniform1FakeLocation, 822 kUniform1RealLocation, 823 kUniform1DesiredLocation, 824 kUniform1Name, 825 }, 826 { kUniform2Name, 827 kUniform2Size, 828 kUniform2BadType, 829 kUniform2FakeLocation, 830 kUniform2RealLocation, 831 kUniform2DesiredLocation, 832 kUniform2Name, 833 }, 834 { kUniform3BadName, 835 kUniform3Size, 836 kUniform3Type, 837 kUniform3FakeLocation, 838 kUniform3RealLocation, 839 kUniform3DesiredLocation, 840 kUniform3GoodName, 841 }, 842 }; 843 const size_t kNumAttribs= arraysize(kAttribs); 844 const size_t kNumUniforms = arraysize(kUniforms); 845 static const GLuint kClientProgramId = 1234; 846 static const GLuint kServiceProgramId = 5679; 847 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 848 kServiceProgramId); 849 Program* program = manager_.CreateProgram( 850 kClientProgramId, kServiceProgramId); 851 ASSERT_TRUE(program!= NULL); 852 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 853 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 854 program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed, 855 base::Bind(&ShaderCacheCb)); 856 // Check that we got the good type, not the bad. 857 // Check Attribs 858 for (unsigned index = 0; index < kNumAttribs; ++index) { 859 const Program::VertexAttrib* attrib_info = 860 program->GetAttribInfo(index); 861 ASSERT_TRUE(attrib_info != NULL); 862 ShaderTranslator::VariableMap::const_iterator it = attrib_map.find( 863 attrib_info->name); 864 ASSERT_TRUE(it != attrib_map.end()); 865 EXPECT_EQ(it->first, attrib_info->name); 866 EXPECT_EQ(static_cast<GLenum>(it->second.type), attrib_info->type); 867 EXPECT_EQ(it->second.size, attrib_info->size); 868 EXPECT_EQ(it->second.name, attrib_info->name); 869 } 870 // Check Uniforms 871 for (unsigned index = 0; index < kNumUniforms; ++index) { 872 const Program::UniformInfo* uniform_info = 873 program->GetUniformInfo(index); 874 ASSERT_TRUE(uniform_info != NULL); 875 ShaderTranslator::VariableMap::const_iterator it = uniform_map.find( 876 uniform_info->name); 877 ASSERT_TRUE(it != uniform_map.end()); 878 EXPECT_EQ(it->first, uniform_info->name); 879 EXPECT_EQ(static_cast<GLenum>(it->second.type), uniform_info->type); 880 EXPECT_EQ(it->second.size, uniform_info->size); 881 EXPECT_EQ(it->second.name, uniform_info->name); 882 } 883 } 884 885 TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount) { 886 static const GLuint kClientProgramId = 124; 887 static const GLuint kServiceProgramId = 457; 888 Program* program = manager_.CreateProgram( 889 kClientProgramId, kServiceProgramId); 890 ASSERT_TRUE(program != NULL); 891 EXPECT_FALSE(program->CanLink()); 892 const GLuint kVShaderClientId = 2001; 893 const GLuint kFShaderClientId = 2002; 894 const GLuint kVShaderServiceId = 3001; 895 const GLuint kFShaderServiceId = 3002; 896 Shader* vshader = shader_manager_.CreateShader( 897 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 898 ASSERT_TRUE(vshader != NULL); 899 TestHelper::SetShaderStates(gl_.get(), vshader, true); 900 Shader* fshader = shader_manager_.CreateShader( 901 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 902 ASSERT_TRUE(fshader != NULL); 903 TestHelper::SetShaderStates(gl_.get(), fshader, true); 904 EXPECT_FALSE(vshader->InUse()); 905 EXPECT_FALSE(fshader->InUse()); 906 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 907 EXPECT_TRUE(vshader->InUse()); 908 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 909 EXPECT_TRUE(fshader->InUse()); 910 EXPECT_TRUE(program->CanLink()); 911 EXPECT_FALSE(program->InUse()); 912 EXPECT_FALSE(program->IsDeleted()); 913 manager_.UseProgram(program); 914 EXPECT_TRUE(program->InUse()); 915 manager_.UseProgram(program); 916 EXPECT_TRUE(program->InUse()); 917 manager_.MarkAsDeleted(&shader_manager_, program); 918 EXPECT_TRUE(program->IsDeleted()); 919 Program* info2 = manager_.GetProgram(kClientProgramId); 920 EXPECT_EQ(program, info2); 921 manager_.UnuseProgram(&shader_manager_, program); 922 EXPECT_TRUE(program->InUse()); 923 // this should delete the info. 924 EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)) 925 .Times(1) 926 .RetiresOnSaturation(); 927 manager_.UnuseProgram(&shader_manager_, program); 928 info2 = manager_.GetProgram(kClientProgramId); 929 EXPECT_TRUE(info2 == NULL); 930 EXPECT_FALSE(vshader->InUse()); 931 EXPECT_FALSE(fshader->InUse()); 932 } 933 934 TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount2) { 935 static const GLuint kClientProgramId = 124; 936 static const GLuint kServiceProgramId = 457; 937 Program* program = manager_.CreateProgram( 938 kClientProgramId, kServiceProgramId); 939 ASSERT_TRUE(program != NULL); 940 EXPECT_FALSE(program->CanLink()); 941 const GLuint kVShaderClientId = 2001; 942 const GLuint kFShaderClientId = 2002; 943 const GLuint kVShaderServiceId = 3001; 944 const GLuint kFShaderServiceId = 3002; 945 Shader* vshader = shader_manager_.CreateShader( 946 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 947 ASSERT_TRUE(vshader != NULL); 948 TestHelper::SetShaderStates(gl_.get(), vshader, true); 949 Shader* fshader = shader_manager_.CreateShader( 950 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 951 ASSERT_TRUE(fshader != NULL); 952 TestHelper::SetShaderStates(gl_.get(), fshader, true); 953 EXPECT_FALSE(vshader->InUse()); 954 EXPECT_FALSE(fshader->InUse()); 955 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 956 EXPECT_TRUE(vshader->InUse()); 957 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 958 EXPECT_TRUE(fshader->InUse()); 959 EXPECT_TRUE(program->CanLink()); 960 EXPECT_FALSE(program->InUse()); 961 EXPECT_FALSE(program->IsDeleted()); 962 manager_.UseProgram(program); 963 EXPECT_TRUE(program->InUse()); 964 manager_.UseProgram(program); 965 EXPECT_TRUE(program->InUse()); 966 manager_.UnuseProgram(&shader_manager_, program); 967 EXPECT_TRUE(program->InUse()); 968 manager_.UnuseProgram(&shader_manager_, program); 969 EXPECT_FALSE(program->InUse()); 970 Program* info2 = manager_.GetProgram(kClientProgramId); 971 EXPECT_EQ(program, info2); 972 // this should delete the program. 973 EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)) 974 .Times(1) 975 .RetiresOnSaturation(); 976 manager_.MarkAsDeleted(&shader_manager_, program); 977 info2 = manager_.GetProgram(kClientProgramId); 978 EXPECT_TRUE(info2 == NULL); 979 EXPECT_FALSE(vshader->InUse()); 980 EXPECT_FALSE(fshader->InUse()); 981 } 982 983 TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetProgramInfo) { 984 CommonDecoder::Bucket bucket; 985 const Program* program = manager_.GetProgram(kClientProgramId); 986 ASSERT_TRUE(program != NULL); 987 program->GetProgramInfo(&manager_, &bucket); 988 ProgramInfoHeader* header = 989 bucket.GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader)); 990 ASSERT_TRUE(header != NULL); 991 EXPECT_EQ(1u, header->link_status); 992 EXPECT_EQ(arraysize(kAttribs), header->num_attribs); 993 EXPECT_EQ(arraysize(kUniforms), header->num_uniforms); 994 const ProgramInput* inputs = bucket.GetDataAs<const ProgramInput*>( 995 sizeof(*header), 996 sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms)); 997 ASSERT_TRUE(inputs != NULL); 998 const ProgramInput* input = inputs; 999 // TODO(gman): Don't assume these are in order. 1000 for (uint32 ii = 0; ii < header->num_attribs; ++ii) { 1001 const AttribInfo& expected = kAttribs[ii]; 1002 EXPECT_EQ(expected.size, input->size); 1003 EXPECT_EQ(expected.type, input->type); 1004 const int32* location = bucket.GetDataAs<const int32*>( 1005 input->location_offset, sizeof(int32)); 1006 ASSERT_TRUE(location != NULL); 1007 EXPECT_EQ(expected.location, *location); 1008 const char* name_buf = bucket.GetDataAs<const char*>( 1009 input->name_offset, input->name_length); 1010 ASSERT_TRUE(name_buf != NULL); 1011 std::string name(name_buf, input->name_length); 1012 EXPECT_STREQ(expected.name, name.c_str()); 1013 ++input; 1014 } 1015 // TODO(gman): Don't assume these are in order. 1016 for (uint32 ii = 0; ii < header->num_uniforms; ++ii) { 1017 const UniformInfo& expected = kUniforms[ii]; 1018 EXPECT_EQ(expected.size, input->size); 1019 EXPECT_EQ(expected.type, input->type); 1020 const int32* locations = bucket.GetDataAs<const int32*>( 1021 input->location_offset, sizeof(int32) * input->size); 1022 ASSERT_TRUE(locations != NULL); 1023 for (int32 jj = 0; jj < input->size; ++jj) { 1024 EXPECT_EQ( 1025 ProgramManager::MakeFakeLocation(expected.fake_location, jj), 1026 locations[jj]); 1027 } 1028 const char* name_buf = bucket.GetDataAs<const char*>( 1029 input->name_offset, input->name_length); 1030 ASSERT_TRUE(name_buf != NULL); 1031 std::string name(name_buf, input->name_length); 1032 EXPECT_STREQ(expected.good_name, name.c_str()); 1033 ++input; 1034 } 1035 EXPECT_EQ(header->num_attribs + header->num_uniforms, 1036 static_cast<uint32>(input - inputs)); 1037 } 1038 1039 // Some drivers optimize out unused uniform array elements, so their 1040 // location would be -1. 1041 TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) { 1042 CommonDecoder::Bucket bucket; 1043 const Program* program = manager_.GetProgram(kClientProgramId); 1044 ASSERT_TRUE(program != NULL); 1045 // Emulate the situation that only the first element has a valid location. 1046 // TODO(zmo): Don't assume these are in order. 1047 for (size_t ii = 0; ii < arraysize(kUniforms); ++ii) { 1048 Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>( 1049 program->GetUniformInfo(ii)); 1050 ASSERT_TRUE(uniform != NULL); 1051 EXPECT_EQ(static_cast<size_t>(kUniforms[ii].size), 1052 uniform->element_locations.size()); 1053 for (GLsizei jj = 1; jj < uniform->size; ++jj) 1054 uniform->element_locations[jj] = -1; 1055 } 1056 program->GetProgramInfo(&manager_, &bucket); 1057 ProgramInfoHeader* header = 1058 bucket.GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader)); 1059 ASSERT_TRUE(header != NULL); 1060 EXPECT_EQ(1u, header->link_status); 1061 EXPECT_EQ(arraysize(kAttribs), header->num_attribs); 1062 EXPECT_EQ(arraysize(kUniforms), header->num_uniforms); 1063 const ProgramInput* inputs = bucket.GetDataAs<const ProgramInput*>( 1064 sizeof(*header), 1065 sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms)); 1066 ASSERT_TRUE(inputs != NULL); 1067 const ProgramInput* input = inputs + header->num_attribs; 1068 for (uint32 ii = 0; ii < header->num_uniforms; ++ii) { 1069 const UniformInfo& expected = kUniforms[ii]; 1070 EXPECT_EQ(expected.size, input->size); 1071 const int32* locations = bucket.GetDataAs<const int32*>( 1072 input->location_offset, sizeof(int32) * input->size); 1073 ASSERT_TRUE(locations != NULL); 1074 EXPECT_EQ( 1075 ProgramManager::MakeFakeLocation(expected.fake_location, 0), 1076 locations[0]); 1077 for (int32 jj = 1; jj < input->size; ++jj) 1078 EXPECT_EQ(-1, locations[jj]); 1079 ++input; 1080 } 1081 } 1082 1083 TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) { 1084 // Set up shader 1085 const GLuint kVShaderClientId = 1; 1086 const GLuint kVShaderServiceId = 11; 1087 const GLuint kFShaderClientId = 2; 1088 const GLuint kFShaderServiceId = 12; 1089 ShaderTranslator::VariableMap attrib_map; 1090 for (uint32 ii = 0; ii < kNumAttribs; ++ii) { 1091 attrib_map[kAttribs[ii].name] = ShaderTranslatorInterface::VariableInfo( 1092 kAttribs[ii].type, 1093 kAttribs[ii].size, 1094 SH_PRECISION_MEDIUMP, 1095 kAttribStaticUse, 1096 kAttribs[ii].name); 1097 } 1098 // Check we can create shader. 1099 Shader* vshader = shader_manager_.CreateShader( 1100 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 1101 Shader* fshader = shader_manager_.CreateShader( 1102 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 1103 // Check shader got created. 1104 ASSERT_TRUE(vshader != NULL && fshader != NULL); 1105 // Set Status 1106 TestHelper::SetShaderStates( 1107 gl_.get(), vshader, true, NULL, NULL, &attrib_map, NULL, NULL, NULL); 1108 // Check attrib infos got copied. 1109 for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin(); 1110 it != attrib_map.end(); ++it) { 1111 const Shader::VariableInfo* variable_info = 1112 vshader->GetAttribInfo(it->first); 1113 ASSERT_TRUE(variable_info != NULL); 1114 EXPECT_EQ(it->second.type, variable_info->type); 1115 EXPECT_EQ(it->second.size, variable_info->size); 1116 EXPECT_EQ(it->second.precision, variable_info->precision); 1117 EXPECT_EQ(it->second.static_use, variable_info->static_use); 1118 EXPECT_EQ(it->second.name, variable_info->name); 1119 } 1120 TestHelper::SetShaderStates( 1121 gl_.get(), fshader, true, NULL, NULL, &attrib_map, NULL, NULL, NULL); 1122 1123 // Set up program 1124 const GLuint kClientProgramId = 6666; 1125 const GLuint kServiceProgramId = 8888; 1126 Program* program = 1127 manager_.CreateProgram(kClientProgramId, kServiceProgramId); 1128 ASSERT_TRUE(program != NULL); 1129 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 1130 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 1131 1132 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts()); 1133 EXPECT_TRUE(LinkAsExpected(program, true)); 1134 1135 program->SetAttribLocationBinding(kAttrib1Name, 0); 1136 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts()); 1137 EXPECT_TRUE(LinkAsExpected(program, true)); 1138 1139 program->SetAttribLocationBinding("xxx", 0); 1140 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts()); 1141 EXPECT_TRUE(LinkAsExpected(program, true)); 1142 1143 program->SetAttribLocationBinding(kAttrib2Name, 1); 1144 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts()); 1145 EXPECT_TRUE(LinkAsExpected(program, true)); 1146 1147 program->SetAttribLocationBinding(kAttrib2Name, 0); 1148 EXPECT_TRUE(program->DetectAttribLocationBindingConflicts()); 1149 EXPECT_TRUE(LinkAsExpected(program, false)); 1150 } 1151 1152 TEST_F(ProgramManagerWithShaderTest, UniformsPrecisionMismatch) { 1153 // Set up shader 1154 const GLuint kVShaderClientId = 1; 1155 const GLuint kVShaderServiceId = 11; 1156 const GLuint kFShaderClientId = 2; 1157 const GLuint kFShaderServiceId = 12; 1158 1159 ShaderTranslator::VariableMap vertex_uniform_map; 1160 vertex_uniform_map["a"] = ShaderTranslator::VariableInfo( 1161 1, 3, SH_PRECISION_MEDIUMP, 1, "a"); 1162 ShaderTranslator::VariableMap frag_uniform_map; 1163 frag_uniform_map["a"] = ShaderTranslator::VariableInfo( 1164 1, 3, SH_PRECISION_LOWP, 1, "a"); 1165 1166 // Check we can create shader. 1167 Shader* vshader = shader_manager_.CreateShader( 1168 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 1169 Shader* fshader = shader_manager_.CreateShader( 1170 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 1171 // Check shader got created. 1172 ASSERT_TRUE(vshader != NULL && fshader != NULL); 1173 // Set Status 1174 TestHelper::SetShaderStates( 1175 gl_.get(), vshader, true, NULL, NULL, NULL, 1176 &vertex_uniform_map, NULL, NULL); 1177 TestHelper::SetShaderStates( 1178 gl_.get(), fshader, true, NULL, NULL, NULL, 1179 &frag_uniform_map, NULL, NULL); 1180 1181 // Set up program 1182 const GLuint kClientProgramId = 6666; 1183 const GLuint kServiceProgramId = 8888; 1184 Program* program = 1185 manager_.CreateProgram(kClientProgramId, kServiceProgramId); 1186 ASSERT_TRUE(program != NULL); 1187 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 1188 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 1189 1190 std::string conflicting_name; 1191 1192 EXPECT_TRUE(program->DetectUniformsMismatch(&conflicting_name)); 1193 EXPECT_EQ("a", conflicting_name); 1194 EXPECT_TRUE(LinkAsExpected(program, false)); 1195 } 1196 1197 // If a varying has different type in the vertex and fragment 1198 // shader, linking should fail. 1199 TEST_F(ProgramManagerWithShaderTest, VaryingTypeMismatch) { 1200 const VarInfo kVertexVarying = 1201 { GL_FLOAT_VEC3, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; 1202 const VarInfo kFragmentVarying = 1203 { GL_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; 1204 Program* program = SetupShaderVariableTest( 1205 &kVertexVarying, 1, &kFragmentVarying, 1); 1206 1207 std::string conflicting_name; 1208 1209 EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name)); 1210 EXPECT_EQ("a", conflicting_name); 1211 EXPECT_TRUE(LinkAsExpected(program, false)); 1212 } 1213 1214 // If a varying has different array size in the vertex and fragment 1215 // shader, linking should fail. 1216 TEST_F(ProgramManagerWithShaderTest, VaryingArraySizeMismatch) { 1217 const VarInfo kVertexVarying = 1218 { GL_FLOAT, 2, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; 1219 const VarInfo kFragmentVarying = 1220 { GL_FLOAT, 3, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; 1221 Program* program = SetupShaderVariableTest( 1222 &kVertexVarying, 1, &kFragmentVarying, 1); 1223 1224 std::string conflicting_name; 1225 1226 EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name)); 1227 EXPECT_EQ("a", conflicting_name); 1228 EXPECT_TRUE(LinkAsExpected(program, false)); 1229 } 1230 1231 // If a varying has different precision in the vertex and fragment 1232 // shader, linking should succeed. 1233 TEST_F(ProgramManagerWithShaderTest, VaryingPrecisionMismatch) { 1234 const VarInfo kVertexVarying = 1235 { GL_FLOAT, 2, SH_PRECISION_HIGHP, 1, "a", kVarVarying }; 1236 const VarInfo kFragmentVarying = 1237 { GL_FLOAT, 2, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; 1238 Program* program = SetupShaderVariableTest( 1239 &kVertexVarying, 1, &kFragmentVarying, 1); 1240 1241 std::string conflicting_name; 1242 1243 EXPECT_FALSE(program->DetectVaryingsMismatch(&conflicting_name)); 1244 EXPECT_TRUE(conflicting_name.empty()); 1245 EXPECT_TRUE(LinkAsExpected(program, true)); 1246 } 1247 1248 // If a varying is statically used in fragment shader but not 1249 // declared in vertex shader, link should fail. 1250 TEST_F(ProgramManagerWithShaderTest, VaryingMissing) { 1251 const VarInfo kFragmentVarying = 1252 { GL_FLOAT, 3, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; 1253 Program* program = SetupShaderVariableTest( 1254 NULL, 0, &kFragmentVarying, 1); 1255 1256 std::string conflicting_name; 1257 1258 EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name)); 1259 EXPECT_EQ("a", conflicting_name); 1260 EXPECT_TRUE(LinkAsExpected(program, false)); 1261 } 1262 1263 // If a varying is declared but not statically used in fragment 1264 // shader, even if it's not declared in vertex shader, link should 1265 // succeed. 1266 TEST_F(ProgramManagerWithShaderTest, InactiveVarying) { 1267 const VarInfo kFragmentVarying = 1268 { GL_FLOAT, 3, SH_PRECISION_MEDIUMP, 0, "a", kVarVarying }; 1269 Program* program = SetupShaderVariableTest( 1270 NULL, 0, &kFragmentVarying, 1); 1271 1272 std::string conflicting_name; 1273 1274 EXPECT_FALSE(program->DetectVaryingsMismatch(&conflicting_name)); 1275 EXPECT_TRUE(conflicting_name.empty()); 1276 EXPECT_TRUE(LinkAsExpected(program, true)); 1277 } 1278 1279 // Uniforms and attributes are both global variables, thus sharing 1280 // the same namespace. Any name conflicts should cause link 1281 // failure. 1282 TEST_F(ProgramManagerWithShaderTest, AttribUniformNameConflict) { 1283 const VarInfo kVertexAttribute = 1284 { GL_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarAttribute }; 1285 const VarInfo kFragmentUniform = 1286 { GL_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarUniform }; 1287 Program* program = SetupShaderVariableTest( 1288 &kVertexAttribute, 1, &kFragmentUniform, 1); 1289 1290 std::string conflicting_name; 1291 1292 EXPECT_TRUE(program->DetectGlobalNameConflicts(&conflicting_name)); 1293 EXPECT_EQ("a", conflicting_name); 1294 EXPECT_TRUE(LinkAsExpected(program, false)); 1295 } 1296 1297 // Varyings go over 8 rows. 1298 TEST_F(ProgramManagerWithShaderTest, TooManyVaryings) { 1299 const VarInfo kVertexVaryings[] = { 1300 { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }, 1301 { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } 1302 }; 1303 const VarInfo kFragmentVaryings[] = { 1304 { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }, 1305 { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } 1306 }; 1307 Program* program = SetupShaderVariableTest( 1308 kVertexVaryings, 2, kFragmentVaryings, 2); 1309 1310 EXPECT_FALSE( 1311 program->CheckVaryingsPacking(Program::kCountOnlyStaticallyUsed)); 1312 EXPECT_TRUE(LinkAsExpected(program, false)); 1313 } 1314 1315 // Varyings go over 8 rows but some are inactive 1316 TEST_F(ProgramManagerWithShaderTest, TooManyInactiveVaryings) { 1317 const VarInfo kVertexVaryings[] = { 1318 { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }, 1319 { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } 1320 }; 1321 const VarInfo kFragmentVaryings[] = { 1322 { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 0, "a", kVarVarying }, 1323 { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } 1324 }; 1325 Program* program = SetupShaderVariableTest( 1326 kVertexVaryings, 2, kFragmentVaryings, 2); 1327 1328 EXPECT_TRUE( 1329 program->CheckVaryingsPacking(Program::kCountOnlyStaticallyUsed)); 1330 EXPECT_TRUE(LinkAsExpected(program, true)); 1331 } 1332 1333 // Varyings go over 8 rows but some are inactive. 1334 // However, we still fail the check if kCountAll option is used. 1335 TEST_F(ProgramManagerWithShaderTest, CountAllVaryingsInPacking) { 1336 const VarInfo kVertexVaryings[] = { 1337 { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }, 1338 { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } 1339 }; 1340 const VarInfo kFragmentVaryings[] = { 1341 { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 0, "a", kVarVarying }, 1342 { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } 1343 }; 1344 Program* program = SetupShaderVariableTest( 1345 kVertexVaryings, 2, kFragmentVaryings, 2); 1346 1347 EXPECT_FALSE(program->CheckVaryingsPacking(Program::kCountAll)); 1348 } 1349 1350 TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) { 1351 const GLuint kVShaderClientId = 2001; 1352 const GLuint kFShaderClientId = 2002; 1353 const GLuint kVShaderServiceId = 3001; 1354 const GLuint kFShaderServiceId = 3002; 1355 Shader* vshader = shader_manager_.CreateShader( 1356 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 1357 ASSERT_TRUE(vshader != NULL); 1358 TestHelper::SetShaderStates(gl_.get(), vshader, true); 1359 Shader* fshader = shader_manager_.CreateShader( 1360 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 1361 ASSERT_TRUE(fshader != NULL); 1362 TestHelper::SetShaderStates(gl_.get(), fshader, true); 1363 static const GLuint kClientProgramId = 1234; 1364 static const GLuint kServiceProgramId = 5679; 1365 Program* program = manager_.CreateProgram( 1366 kClientProgramId, kServiceProgramId); 1367 ASSERT_TRUE(program != NULL); 1368 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 1369 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 1370 1371 static const GLenum kSamplerTypes[] = { 1372 GL_SAMPLER_2D, 1373 GL_SAMPLER_CUBE, 1374 GL_SAMPLER_EXTERNAL_OES, 1375 GL_SAMPLER_3D_OES, 1376 GL_SAMPLER_2D_RECT_ARB, 1377 }; 1378 const size_t kNumSamplerTypes = arraysize(kSamplerTypes); 1379 for (size_t ii = 0; ii < kNumSamplerTypes; ++ii) { 1380 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = { 1381 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, 1382 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, 1383 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, 1384 }; 1385 ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 1386 { kUniform1Name, 1387 kUniform1Size, 1388 kUniform1Type, 1389 kUniform1FakeLocation, 1390 kUniform1RealLocation, 1391 kUniform1DesiredLocation, 1392 kUniform1Name, 1393 }, 1394 { kUniform2Name, 1395 kUniform2Size, 1396 kSamplerTypes[ii], 1397 kUniform2FakeLocation, 1398 kUniform2RealLocation, 1399 kUniform2DesiredLocation, 1400 kUniform2Name, 1401 }, 1402 { kUniform3BadName, 1403 kUniform3Size, 1404 kUniform3Type, 1405 kUniform3FakeLocation, 1406 kUniform3RealLocation, 1407 kUniform3DesiredLocation, 1408 kUniform3GoodName, 1409 }, 1410 }; 1411 const size_t kNumAttribs = arraysize(kAttribs); 1412 const size_t kNumUniforms = arraysize(kUniforms); 1413 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 1414 kServiceProgramId); 1415 program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed, 1416 base::Bind(&ShaderCacheCb)); 1417 SetupExpectationsForClearingUniforms(kUniforms, kNumUniforms); 1418 manager_.ClearUniforms(program); 1419 } 1420 } 1421 1422 TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) { 1423 const GLuint kVShaderClientId = 2001; 1424 const GLuint kFShaderClientId = 2002; 1425 const GLuint kVShaderServiceId = 3001; 1426 const GLuint kFShaderServiceId = 3002; 1427 1428 const GLint kUniform1DesiredLocation = 10; 1429 const GLint kUniform2DesiredLocation = -1; 1430 const GLint kUniform3DesiredLocation = 5; 1431 1432 Shader* vshader = shader_manager_.CreateShader( 1433 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 1434 ASSERT_TRUE(vshader != NULL); 1435 TestHelper::SetShaderStates(gl_.get(), vshader, true); 1436 Shader* fshader = shader_manager_.CreateShader( 1437 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 1438 ASSERT_TRUE(fshader != NULL); 1439 TestHelper::SetShaderStates(gl_.get(), fshader, true); 1440 static const GLuint kClientProgramId = 1234; 1441 static const GLuint kServiceProgramId = 5679; 1442 Program* program = manager_.CreateProgram( 1443 kClientProgramId, kServiceProgramId); 1444 ASSERT_TRUE(program != NULL); 1445 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 1446 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 1447 EXPECT_TRUE(program->SetUniformLocationBinding( 1448 kUniform1Name, kUniform1DesiredLocation)); 1449 EXPECT_TRUE(program->SetUniformLocationBinding( 1450 kUniform3BadName, kUniform3DesiredLocation)); 1451 1452 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = { 1453 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, 1454 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, 1455 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, 1456 }; 1457 ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 1458 { kUniform1Name, 1459 kUniform1Size, 1460 kUniform1Type, 1461 kUniform1FakeLocation, 1462 kUniform1RealLocation, 1463 kUniform1DesiredLocation, 1464 kUniform1Name, 1465 }, 1466 { kUniform2Name, 1467 kUniform2Size, 1468 kUniform2Type, 1469 kUniform2FakeLocation, 1470 kUniform2RealLocation, 1471 kUniform2DesiredLocation, 1472 kUniform2Name, 1473 }, 1474 { kUniform3BadName, 1475 kUniform3Size, 1476 kUniform3Type, 1477 kUniform3FakeLocation, 1478 kUniform3RealLocation, 1479 kUniform3DesiredLocation, 1480 kUniform3GoodName, 1481 }, 1482 }; 1483 1484 const size_t kNumAttribs = arraysize(kAttribs); 1485 const size_t kNumUniforms = arraysize(kUniforms); 1486 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 1487 kServiceProgramId); 1488 program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed, 1489 base::Bind(&ShaderCacheCb)); 1490 1491 EXPECT_EQ(kUniform1DesiredLocation, 1492 program->GetUniformFakeLocation(kUniform1Name)); 1493 EXPECT_EQ(kUniform3DesiredLocation, 1494 program->GetUniformFakeLocation(kUniform3BadName)); 1495 EXPECT_EQ(kUniform3DesiredLocation, 1496 program->GetUniformFakeLocation(kUniform3GoodName)); 1497 } 1498 1499 class ProgramManagerWithCacheTest : public GpuServiceTest { 1500 public: 1501 static const GLuint kClientProgramId = 1; 1502 static const GLuint kServiceProgramId = 10; 1503 static const GLuint kVertexShaderClientId = 2; 1504 static const GLuint kFragmentShaderClientId = 20; 1505 static const GLuint kVertexShaderServiceId = 3; 1506 static const GLuint kFragmentShaderServiceId = 30; 1507 1508 ProgramManagerWithCacheTest() 1509 : cache_(new MockProgramCache()), 1510 manager_(cache_.get(), kMaxVaryingVectors), 1511 vertex_shader_(NULL), 1512 fragment_shader_(NULL), 1513 program_(NULL) { 1514 } 1515 virtual ~ProgramManagerWithCacheTest() { 1516 manager_.Destroy(false); 1517 shader_manager_.Destroy(false); 1518 } 1519 1520 protected: 1521 virtual void SetUp() { 1522 GpuServiceTest::SetUp(); 1523 1524 vertex_shader_ = shader_manager_.CreateShader( 1525 kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER); 1526 fragment_shader_ = shader_manager_.CreateShader( 1527 kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER); 1528 ASSERT_TRUE(vertex_shader_ != NULL); 1529 ASSERT_TRUE(fragment_shader_ != NULL); 1530 vertex_shader_->set_source("lka asjf bjajsdfj"); 1531 fragment_shader_->set_source("lka asjf a fasgag 3rdsf3 bjajsdfj"); 1532 1533 program_ = manager_.CreateProgram( 1534 kClientProgramId, kServiceProgramId); 1535 ASSERT_TRUE(program_ != NULL); 1536 1537 program_->AttachShader(&shader_manager_, vertex_shader_); 1538 program_->AttachShader(&shader_manager_, fragment_shader_); 1539 } 1540 1541 void SetShadersCompiled() { 1542 TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true); 1543 TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true); 1544 } 1545 1546 void SetProgramCached() { 1547 cache_->LinkedProgramCacheSuccess( 1548 vertex_shader_->source(), 1549 NULL, 1550 fragment_shader_->source(), 1551 NULL, 1552 &program_->bind_attrib_location_map()); 1553 } 1554 1555 void SetExpectationsForProgramCached() { 1556 SetExpectationsForProgramCached(program_, 1557 vertex_shader_, 1558 fragment_shader_); 1559 } 1560 1561 void SetExpectationsForProgramCached( 1562 Program* program, 1563 Shader* vertex_shader, 1564 Shader* fragment_shader) { 1565 EXPECT_CALL(*cache_.get(), SaveLinkedProgram( 1566 program->service_id(), 1567 vertex_shader, 1568 NULL, 1569 fragment_shader, 1570 NULL, 1571 &program->bind_attrib_location_map(), 1572 _)).Times(1); 1573 } 1574 1575 void SetExpectationsForNotCachingProgram() { 1576 SetExpectationsForNotCachingProgram(program_, 1577 vertex_shader_, 1578 fragment_shader_); 1579 } 1580 1581 void SetExpectationsForNotCachingProgram( 1582 Program* program, 1583 Shader* vertex_shader, 1584 Shader* fragment_shader) { 1585 EXPECT_CALL(*cache_.get(), SaveLinkedProgram( 1586 program->service_id(), 1587 vertex_shader, 1588 NULL, 1589 fragment_shader, 1590 NULL, 1591 &program->bind_attrib_location_map(), 1592 _)).Times(0); 1593 } 1594 1595 void SetExpectationsForProgramLoad(ProgramCache::ProgramLoadResult result) { 1596 SetExpectationsForProgramLoad(kServiceProgramId, 1597 program_, 1598 vertex_shader_, 1599 fragment_shader_, 1600 result); 1601 } 1602 1603 void SetExpectationsForProgramLoad( 1604 GLuint service_program_id, 1605 Program* program, 1606 Shader* vertex_shader, 1607 Shader* fragment_shader, 1608 ProgramCache::ProgramLoadResult result) { 1609 EXPECT_CALL(*cache_.get(), 1610 LoadLinkedProgram(service_program_id, 1611 vertex_shader, 1612 NULL, 1613 fragment_shader, 1614 NULL, 1615 &program->bind_attrib_location_map(), 1616 _)) 1617 .WillOnce(Return(result)); 1618 } 1619 1620 void SetExpectationsForProgramLoadSuccess() { 1621 SetExpectationsForProgramLoadSuccess(kServiceProgramId); 1622 } 1623 1624 void SetExpectationsForProgramLoadSuccess(GLuint service_program_id) { 1625 TestHelper::SetupProgramSuccessExpectations(gl_.get(), 1626 NULL, 1627 0, 1628 NULL, 1629 0, 1630 service_program_id); 1631 } 1632 1633 void SetExpectationsForProgramLink() { 1634 SetExpectationsForProgramLink(kServiceProgramId); 1635 } 1636 1637 void SetExpectationsForProgramLink(GLuint service_program_id) { 1638 TestHelper::SetupShader(gl_.get(), NULL, 0, NULL, 0, service_program_id); 1639 if (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) { 1640 EXPECT_CALL(*gl_.get(), 1641 ProgramParameteri(service_program_id, 1642 PROGRAM_BINARY_RETRIEVABLE_HINT, 1643 GL_TRUE)).Times(1); 1644 } 1645 } 1646 1647 void SetExpectationsForSuccessCompile( 1648 const Shader* shader) { 1649 const GLuint shader_id = shader->service_id(); 1650 const char* src = shader->source().c_str(); 1651 EXPECT_CALL(*gl_.get(), 1652 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); 1653 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); 1654 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) 1655 .WillOnce(SetArgumentPointee<2>(GL_TRUE)); 1656 } 1657 1658 void SetExpectationsForNoCompile(const Shader* shader) { 1659 const GLuint shader_id = shader->service_id(); 1660 const char* src = shader->source().c_str(); 1661 EXPECT_CALL(*gl_.get(), 1662 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); 1663 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); 1664 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) 1665 .Times(0); 1666 } 1667 1668 void SetExpectationsForErrorCompile(const Shader* shader) { 1669 const GLuint shader_id = shader->service_id(); 1670 const char* src = shader->source().c_str(); 1671 EXPECT_CALL(*gl_.get(), 1672 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); 1673 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); 1674 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) 1675 .WillOnce(SetArgumentPointee<2>(GL_FALSE)); 1676 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) 1677 .WillOnce(SetArgumentPointee<2>(0)); 1678 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) 1679 .Times(1); 1680 } 1681 1682 scoped_ptr<MockProgramCache> cache_; 1683 ProgramManager manager_; 1684 1685 Shader* vertex_shader_; 1686 Shader* fragment_shader_; 1687 Program* program_; 1688 ShaderManager shader_manager_; 1689 }; 1690 1691 // GCC requires these declarations, but MSVC requires they not be present 1692 #ifndef COMPILER_MSVC 1693 const GLuint ProgramManagerWithCacheTest::kClientProgramId; 1694 const GLuint ProgramManagerWithCacheTest::kServiceProgramId; 1695 const GLuint ProgramManagerWithCacheTest::kVertexShaderClientId; 1696 const GLuint ProgramManagerWithCacheTest::kFragmentShaderClientId; 1697 const GLuint ProgramManagerWithCacheTest::kVertexShaderServiceId; 1698 const GLuint ProgramManagerWithCacheTest::kFragmentShaderServiceId; 1699 #endif 1700 1701 TEST_F(ProgramManagerWithCacheTest, CacheProgramOnSuccessfulLink) { 1702 SetShadersCompiled(); 1703 SetExpectationsForProgramLink(); 1704 SetExpectationsForProgramCached(); 1705 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, 1706 Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb))); 1707 } 1708 1709 TEST_F(ProgramManagerWithCacheTest, LoadProgramOnProgramCacheHit) { 1710 SetShadersCompiled(); 1711 SetProgramCached(); 1712 1713 SetExpectationsForNoCompile(vertex_shader_); 1714 SetExpectationsForNoCompile(fragment_shader_); 1715 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); 1716 SetExpectationsForNotCachingProgram(); 1717 SetExpectationsForProgramLoadSuccess(); 1718 1719 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, 1720 Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb))); 1721 } 1722 1723 } // namespace gles2 1724 } // namespace gpu 1725