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