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 void ShaderCacheCb(const std::string& key, const std::string& shader) {} 40 } // namespace 41 42 class ProgramManagerTest : public testing::Test { 43 public: 44 ProgramManagerTest() : manager_(NULL) { } 45 virtual ~ProgramManagerTest() { 46 manager_.Destroy(false); 47 } 48 49 protected: 50 virtual void SetUp() { 51 gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); 52 ::gfx::GLInterface::SetGLInterface(gl_.get()); 53 } 54 55 virtual void TearDown() { 56 ::gfx::GLInterface::SetGLInterface(NULL); 57 gl_.reset(); 58 } 59 60 // Use StrictMock to make 100% sure we know how GL will be called. 61 scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; 62 ProgramManager manager_; 63 }; 64 65 TEST_F(ProgramManagerTest, Basic) { 66 const GLuint kClient1Id = 1; 67 const GLuint kService1Id = 11; 68 const GLuint kClient2Id = 2; 69 // Check we can create program. 70 manager_.CreateProgram(kClient1Id, kService1Id); 71 // Check program got created. 72 Program* program1 = manager_.GetProgram(kClient1Id); 73 ASSERT_TRUE(program1 != NULL); 74 GLuint client_id = 0; 75 EXPECT_TRUE(manager_.GetClientId(program1->service_id(), &client_id)); 76 EXPECT_EQ(kClient1Id, client_id); 77 // Check we get nothing for a non-existent program. 78 EXPECT_TRUE(manager_.GetProgram(kClient2Id) == NULL); 79 } 80 81 TEST_F(ProgramManagerTest, Destroy) { 82 const GLuint kClient1Id = 1; 83 const GLuint kService1Id = 11; 84 // Check we can create program. 85 Program* program0 = manager_.CreateProgram(kClient1Id, kService1Id); 86 ASSERT_TRUE(program0 != NULL); 87 // Check program got created. 88 Program* program1 = manager_.GetProgram(kClient1Id); 89 ASSERT_EQ(program0, program1); 90 EXPECT_CALL(*gl_, DeleteProgram(kService1Id)) 91 .Times(1) 92 .RetiresOnSaturation(); 93 manager_.Destroy(true); 94 // Check the resources were released. 95 program1 = manager_.GetProgram(kClient1Id); 96 ASSERT_TRUE(program1 == NULL); 97 } 98 99 TEST_F(ProgramManagerTest, DeleteBug) { 100 ShaderManager shader_manager; 101 const GLuint kClient1Id = 1; 102 const GLuint kClient2Id = 2; 103 const GLuint kService1Id = 11; 104 const GLuint kService2Id = 12; 105 // Check we can create program. 106 scoped_refptr<Program> program1( 107 manager_.CreateProgram(kClient1Id, kService1Id)); 108 scoped_refptr<Program> program2( 109 manager_.CreateProgram(kClient2Id, kService2Id)); 110 // Check program got created. 111 ASSERT_TRUE(program1.get()); 112 ASSERT_TRUE(program2.get()); 113 manager_.UseProgram(program1.get()); 114 manager_.MarkAsDeleted(&shader_manager, program1.get()); 115 // Program will be deleted when last ref is released. 116 EXPECT_CALL(*gl_, DeleteProgram(kService2Id)) 117 .Times(1) 118 .RetiresOnSaturation(); 119 manager_.MarkAsDeleted(&shader_manager, program2.get()); 120 EXPECT_TRUE(manager_.IsOwned(program1.get())); 121 EXPECT_FALSE(manager_.IsOwned(program2.get())); 122 } 123 124 TEST_F(ProgramManagerTest, Program) { 125 const GLuint kClient1Id = 1; 126 const GLuint kService1Id = 11; 127 // Check we can create program. 128 Program* program1 = manager_.CreateProgram( 129 kClient1Id, kService1Id); 130 ASSERT_TRUE(program1); 131 EXPECT_EQ(kService1Id, program1->service_id()); 132 EXPECT_FALSE(program1->InUse()); 133 EXPECT_FALSE(program1->IsValid()); 134 EXPECT_FALSE(program1->IsDeleted()); 135 EXPECT_FALSE(program1->CanLink()); 136 EXPECT_TRUE(program1->log_info() == NULL); 137 } 138 139 class ProgramManagerWithShaderTest : public testing::Test { 140 public: 141 ProgramManagerWithShaderTest() 142 : manager_(NULL), program_(NULL) { 143 } 144 145 virtual ~ProgramManagerWithShaderTest() { 146 manager_.Destroy(false); 147 shader_manager_.Destroy(false); 148 } 149 150 static const GLint kNumVertexAttribs = 16; 151 152 static const GLuint kClientProgramId = 123; 153 static const GLuint kServiceProgramId = 456; 154 static const GLuint kVertexShaderClientId = 201; 155 static const GLuint kFragmentShaderClientId = 202; 156 static const GLuint kVertexShaderServiceId = 301; 157 static const GLuint kFragmentShaderServiceId = 302; 158 159 static const char* kAttrib1Name; 160 static const char* kAttrib2Name; 161 static const char* kAttrib3Name; 162 static const GLint kAttrib1Size = 1; 163 static const GLint kAttrib2Size = 1; 164 static const GLint kAttrib3Size = 1; 165 static const GLint kAttrib1Location = 0; 166 static const GLint kAttrib2Location = 1; 167 static const GLint kAttrib3Location = 2; 168 static const GLenum kAttrib1Type = GL_FLOAT_VEC4; 169 static const GLenum kAttrib2Type = GL_FLOAT_VEC2; 170 static const GLenum kAttrib3Type = GL_FLOAT_VEC3; 171 static const GLint kInvalidAttribLocation = 30; 172 static const GLint kBadAttribIndex = kNumVertexAttribs; 173 174 static const char* kUniform1Name; 175 static const char* kUniform2Name; 176 static const char* kUniform3BadName; 177 static const char* kUniform3GoodName; 178 static const GLint kUniform1Size = 1; 179 static const GLint kUniform2Size = 3; 180 static const GLint kUniform3Size = 2; 181 static const GLint kUniform1FakeLocation = 0; // These are hard coded 182 static const GLint kUniform2FakeLocation = 1; // to match 183 static const GLint kUniform3FakeLocation = 2; // ProgramManager. 184 static const GLint kUniform1RealLocation = 11; 185 static const GLint kUniform2RealLocation = 22; 186 static const GLint kUniform3RealLocation = 33; 187 static const GLint kUniform1DesiredLocation = -1; 188 static const GLint kUniform2DesiredLocation = -1; 189 static const GLint kUniform3DesiredLocation = -1; 190 static const GLenum kUniform1Type = GL_FLOAT_VEC4; 191 static const GLenum kUniform2Type = GL_INT_VEC2; 192 static const GLenum kUniform3Type = GL_FLOAT_VEC3; 193 static const GLint kInvalidUniformLocation = 30; 194 static const GLint kBadUniformIndex = 1000; 195 196 static const size_t kNumAttribs; 197 static const size_t kNumUniforms; 198 199 protected: 200 typedef TestHelper::AttribInfo AttribInfo; 201 typedef TestHelper::UniformInfo UniformInfo; 202 203 virtual void SetUp() { 204 gl_.reset(new StrictMock<gfx::MockGLInterface>()); 205 ::gfx::GLInterface::SetGLInterface(gl_.get()); 206 207 SetupDefaultShaderExpectations(); 208 209 Shader* vertex_shader = shader_manager_.CreateShader( 210 kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER); 211 Shader* fragment_shader = 212 shader_manager_.CreateShader( 213 kFragmentShaderClientId, kFragmentShaderServiceId, 214 GL_FRAGMENT_SHADER); 215 ASSERT_TRUE(vertex_shader != NULL); 216 ASSERT_TRUE(fragment_shader != NULL); 217 vertex_shader->SetStatus(true, NULL, NULL); 218 fragment_shader->SetStatus(true, NULL, NULL); 219 220 program_ = manager_.CreateProgram( 221 kClientProgramId, kServiceProgramId); 222 ASSERT_TRUE(program_ != NULL); 223 224 program_->AttachShader(&shader_manager_, vertex_shader); 225 program_->AttachShader(&shader_manager_, fragment_shader); 226 program_->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb)); 227 } 228 229 void SetupShader(AttribInfo* attribs, size_t num_attribs, 230 UniformInfo* uniforms, size_t num_uniforms, 231 GLuint service_id) { 232 TestHelper::SetupShader( 233 gl_.get(), attribs, num_attribs, uniforms, num_uniforms, service_id); 234 } 235 236 void SetupDefaultShaderExpectations() { 237 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 238 kServiceProgramId); 239 } 240 241 void SetupExpectationsForClearingUniforms( 242 UniformInfo* uniforms, size_t num_uniforms) { 243 TestHelper::SetupExpectationsForClearingUniforms( 244 gl_.get(), uniforms, num_uniforms); 245 } 246 247 virtual void TearDown() { 248 ::gfx::GLInterface::SetGLInterface(NULL); 249 } 250 251 // Return true if link status matches expected_link_status 252 bool LinkAsExpected(Program* program, 253 bool expected_link_status) { 254 GLuint service_id = program->service_id(); 255 if (expected_link_status) { 256 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 257 service_id); 258 } 259 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb)); 260 GLint link_status; 261 program->GetProgramiv(GL_LINK_STATUS, &link_status); 262 return (static_cast<bool>(link_status) == expected_link_status); 263 } 264 265 static AttribInfo kAttribs[]; 266 static UniformInfo kUniforms[]; 267 268 scoped_ptr<StrictMock<gfx::MockGLInterface> > gl_; 269 270 ProgramManager manager_; 271 Program* program_; 272 ShaderManager shader_manager_; 273 }; 274 275 ProgramManagerWithShaderTest::AttribInfo 276 ProgramManagerWithShaderTest::kAttribs[] = { 277 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, 278 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, 279 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, 280 }; 281 282 // GCC requires these declarations, but MSVC requires they not be present 283 #ifndef COMPILER_MSVC 284 const GLint ProgramManagerWithShaderTest::kNumVertexAttribs; 285 const GLuint ProgramManagerWithShaderTest::kClientProgramId; 286 const GLuint ProgramManagerWithShaderTest::kServiceProgramId; 287 const GLuint ProgramManagerWithShaderTest::kVertexShaderClientId; 288 const GLuint ProgramManagerWithShaderTest::kFragmentShaderClientId; 289 const GLuint ProgramManagerWithShaderTest::kVertexShaderServiceId; 290 const GLuint ProgramManagerWithShaderTest::kFragmentShaderServiceId; 291 const GLint ProgramManagerWithShaderTest::kAttrib1Size; 292 const GLint ProgramManagerWithShaderTest::kAttrib2Size; 293 const GLint ProgramManagerWithShaderTest::kAttrib3Size; 294 const GLint ProgramManagerWithShaderTest::kAttrib1Location; 295 const GLint ProgramManagerWithShaderTest::kAttrib2Location; 296 const GLint ProgramManagerWithShaderTest::kAttrib3Location; 297 const GLenum ProgramManagerWithShaderTest::kAttrib1Type; 298 const GLenum ProgramManagerWithShaderTest::kAttrib2Type; 299 const GLenum ProgramManagerWithShaderTest::kAttrib3Type; 300 const GLint ProgramManagerWithShaderTest::kInvalidAttribLocation; 301 const GLint ProgramManagerWithShaderTest::kBadAttribIndex; 302 const GLint ProgramManagerWithShaderTest::kUniform1Size; 303 const GLint ProgramManagerWithShaderTest::kUniform2Size; 304 const GLint ProgramManagerWithShaderTest::kUniform3Size; 305 const GLint ProgramManagerWithShaderTest::kUniform1FakeLocation; 306 const GLint ProgramManagerWithShaderTest::kUniform2FakeLocation; 307 const GLint ProgramManagerWithShaderTest::kUniform3FakeLocation; 308 const GLint ProgramManagerWithShaderTest::kUniform1RealLocation; 309 const GLint ProgramManagerWithShaderTest::kUniform2RealLocation; 310 const GLint ProgramManagerWithShaderTest::kUniform3RealLocation; 311 const GLint ProgramManagerWithShaderTest::kUniform1DesiredLocation; 312 const GLint ProgramManagerWithShaderTest::kUniform2DesiredLocation; 313 const GLint ProgramManagerWithShaderTest::kUniform3DesiredLocation; 314 const GLenum ProgramManagerWithShaderTest::kUniform1Type; 315 const GLenum ProgramManagerWithShaderTest::kUniform2Type; 316 const GLenum ProgramManagerWithShaderTest::kUniform3Type; 317 const GLint ProgramManagerWithShaderTest::kInvalidUniformLocation; 318 const GLint ProgramManagerWithShaderTest::kBadUniformIndex; 319 #endif 320 321 const size_t ProgramManagerWithShaderTest::kNumAttribs = 322 arraysize(ProgramManagerWithShaderTest::kAttribs); 323 324 ProgramManagerWithShaderTest::UniformInfo 325 ProgramManagerWithShaderTest::kUniforms[] = { 326 { kUniform1Name, 327 kUniform1Size, 328 kUniform1Type, 329 kUniform1FakeLocation, 330 kUniform1RealLocation, 331 kUniform1DesiredLocation, 332 kUniform1Name, 333 }, 334 { kUniform2Name, 335 kUniform2Size, 336 kUniform2Type, 337 kUniform2FakeLocation, 338 kUniform2RealLocation, 339 kUniform2DesiredLocation, 340 kUniform2Name, 341 }, 342 { kUniform3BadName, 343 kUniform3Size, 344 kUniform3Type, 345 kUniform3FakeLocation, 346 kUniform3RealLocation, 347 kUniform3DesiredLocation, 348 kUniform3GoodName, 349 }, 350 }; 351 352 const size_t ProgramManagerWithShaderTest::kNumUniforms = 353 arraysize(ProgramManagerWithShaderTest::kUniforms); 354 355 const char* ProgramManagerWithShaderTest::kAttrib1Name = "attrib1"; 356 const char* ProgramManagerWithShaderTest::kAttrib2Name = "attrib2"; 357 const char* ProgramManagerWithShaderTest::kAttrib3Name = "attrib3"; 358 const char* ProgramManagerWithShaderTest::kUniform1Name = "uniform1"; 359 // Correctly has array spec. 360 const char* ProgramManagerWithShaderTest::kUniform2Name = "uniform2[0]"; 361 // Incorrectly missing array spec. 362 const char* ProgramManagerWithShaderTest::kUniform3BadName = "uniform3"; 363 const char* ProgramManagerWithShaderTest::kUniform3GoodName = "uniform3[0]"; 364 365 TEST_F(ProgramManagerWithShaderTest, GetAttribInfos) { 366 const Program* program = manager_.GetProgram(kClientProgramId); 367 ASSERT_TRUE(program != NULL); 368 const Program::AttribInfoVector& infos = 369 program->GetAttribInfos(); 370 ASSERT_EQ(kNumAttribs, infos.size()); 371 for (size_t ii = 0; ii < kNumAttribs; ++ii) { 372 const Program::VertexAttrib& info = infos[ii]; 373 const AttribInfo& expected = kAttribs[ii]; 374 EXPECT_EQ(expected.size, info.size); 375 EXPECT_EQ(expected.type, info.type); 376 EXPECT_EQ(expected.location, info.location); 377 EXPECT_STREQ(expected.name, info.name.c_str()); 378 } 379 } 380 381 TEST_F(ProgramManagerWithShaderTest, GetAttribInfo) { 382 const GLint kValidIndex = 1; 383 const GLint kInvalidIndex = 1000; 384 const Program* program = manager_.GetProgram(kClientProgramId); 385 ASSERT_TRUE(program != NULL); 386 const Program::VertexAttrib* info = 387 program->GetAttribInfo(kValidIndex); 388 ASSERT_TRUE(info != NULL); 389 EXPECT_EQ(kAttrib2Size, info->size); 390 EXPECT_EQ(kAttrib2Type, info->type); 391 EXPECT_EQ(kAttrib2Location, info->location); 392 EXPECT_STREQ(kAttrib2Name, info->name.c_str()); 393 EXPECT_TRUE(program->GetAttribInfo(kInvalidIndex) == NULL); 394 } 395 396 TEST_F(ProgramManagerWithShaderTest, GetAttribLocation) { 397 const char* kInvalidName = "foo"; 398 const Program* program = manager_.GetProgram(kClientProgramId); 399 ASSERT_TRUE(program != NULL); 400 EXPECT_EQ(kAttrib2Location, program->GetAttribLocation(kAttrib2Name)); 401 EXPECT_EQ(-1, program->GetAttribLocation(kInvalidName)); 402 } 403 404 TEST_F(ProgramManagerWithShaderTest, GetUniformInfo) { 405 const GLint kInvalidIndex = 1000; 406 const Program* program = manager_.GetProgram(kClientProgramId); 407 ASSERT_TRUE(program != NULL); 408 const Program::UniformInfo* info = 409 program->GetUniformInfo(0); 410 ASSERT_TRUE(info != NULL); 411 EXPECT_EQ(kUniform1Size, info->size); 412 EXPECT_EQ(kUniform1Type, info->type); 413 EXPECT_EQ(kUniform1RealLocation, info->element_locations[0]); 414 EXPECT_STREQ(kUniform1Name, info->name.c_str()); 415 info = program->GetUniformInfo(1); 416 ASSERT_TRUE(info != NULL); 417 EXPECT_EQ(kUniform2Size, info->size); 418 EXPECT_EQ(kUniform2Type, info->type); 419 EXPECT_EQ(kUniform2RealLocation, info->element_locations[0]); 420 EXPECT_STREQ(kUniform2Name, info->name.c_str()); 421 info = program->GetUniformInfo(2); 422 // We emulate certain OpenGL drivers by supplying the name without 423 // the array spec. Our implementation should correctly add the required spec. 424 ASSERT_TRUE(info != NULL); 425 EXPECT_EQ(kUniform3Size, info->size); 426 EXPECT_EQ(kUniform3Type, info->type); 427 EXPECT_EQ(kUniform3RealLocation, info->element_locations[0]); 428 EXPECT_STREQ(kUniform3GoodName, info->name.c_str()); 429 EXPECT_TRUE(program->GetUniformInfo(kInvalidIndex) == NULL); 430 } 431 432 TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) { 433 static const GLuint kClientProgramId = 124; 434 static const GLuint kServiceProgramId = 457; 435 Program* program = manager_.CreateProgram( 436 kClientProgramId, kServiceProgramId); 437 ASSERT_TRUE(program != NULL); 438 EXPECT_FALSE(program->CanLink()); 439 const GLuint kVShaderClientId = 2001; 440 const GLuint kFShaderClientId = 2002; 441 const GLuint kVShaderServiceId = 3001; 442 const GLuint kFShaderServiceId = 3002; 443 Shader* vshader = shader_manager_.CreateShader( 444 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 445 ASSERT_TRUE(vshader != NULL); 446 vshader->SetStatus(true, "", NULL); 447 Shader* fshader = shader_manager_.CreateShader( 448 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 449 ASSERT_TRUE(fshader != NULL); 450 fshader->SetStatus(true, "", NULL); 451 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 452 EXPECT_FALSE(program->CanLink()); 453 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 454 EXPECT_TRUE(program->CanLink()); 455 program->DetachShader(&shader_manager_, vshader); 456 EXPECT_FALSE(program->CanLink()); 457 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 458 EXPECT_TRUE(program->CanLink()); 459 program->DetachShader(&shader_manager_, fshader); 460 EXPECT_FALSE(program->CanLink()); 461 EXPECT_FALSE(program->AttachShader(&shader_manager_, vshader)); 462 EXPECT_FALSE(program->CanLink()); 463 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 464 EXPECT_TRUE(program->CanLink()); 465 vshader->SetStatus(false, "", NULL); 466 EXPECT_FALSE(program->CanLink()); 467 vshader->SetStatus(true, "", NULL); 468 EXPECT_TRUE(program->CanLink()); 469 fshader->SetStatus(false, "", NULL); 470 EXPECT_FALSE(program->CanLink()); 471 fshader->SetStatus(true, "", NULL); 472 EXPECT_TRUE(program->CanLink()); 473 EXPECT_TRUE(program->DetachShader(&shader_manager_, fshader)); 474 EXPECT_FALSE(program->DetachShader(&shader_manager_, fshader)); 475 } 476 477 TEST_F(ProgramManagerWithShaderTest, GetUniformFakeLocation) { 478 const Program* program = manager_.GetProgram(kClientProgramId); 479 ASSERT_TRUE(program != NULL); 480 EXPECT_EQ(kUniform1FakeLocation, 481 program->GetUniformFakeLocation(kUniform1Name)); 482 EXPECT_EQ(kUniform2FakeLocation, 483 program->GetUniformFakeLocation(kUniform2Name)); 484 EXPECT_EQ(kUniform3FakeLocation, 485 program->GetUniformFakeLocation(kUniform3BadName)); 486 // Check we can get uniform2 as "uniform2" even though the name is 487 // "uniform2[0]" 488 EXPECT_EQ(kUniform2FakeLocation, 489 program->GetUniformFakeLocation("uniform2")); 490 // Check we can get uniform3 as "uniform3[0]" even though we simulated GL 491 // returning "uniform3" 492 EXPECT_EQ(kUniform3FakeLocation, 493 program->GetUniformFakeLocation(kUniform3GoodName)); 494 // Check that we can get the locations of the array elements > 1 495 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation, 1), 496 program->GetUniformFakeLocation("uniform2[1]")); 497 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation, 2), 498 program->GetUniformFakeLocation("uniform2[2]")); 499 EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform2[3]")); 500 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform3FakeLocation, 1), 501 program->GetUniformFakeLocation("uniform3[1]")); 502 EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform3[2]")); 503 } 504 505 TEST_F(ProgramManagerWithShaderTest, GetUniformInfoByFakeLocation) { 506 const GLint kInvalidLocation = 1234; 507 const Program::UniformInfo* info; 508 const Program* program = manager_.GetProgram(kClientProgramId); 509 GLint real_location = -1; 510 GLint array_index = -1; 511 ASSERT_TRUE(program != NULL); 512 info = program->GetUniformInfoByFakeLocation( 513 kUniform2FakeLocation, &real_location, &array_index); 514 EXPECT_EQ(kUniform2RealLocation, real_location); 515 EXPECT_EQ(0, array_index); 516 ASSERT_TRUE(info != NULL); 517 EXPECT_EQ(kUniform2Type, info->type); 518 real_location = -1; 519 array_index = -1; 520 info = program->GetUniformInfoByFakeLocation( 521 kInvalidLocation, &real_location, &array_index); 522 EXPECT_TRUE(info == NULL); 523 EXPECT_EQ(-1, real_location); 524 EXPECT_EQ(-1, array_index); 525 GLint loc = program->GetUniformFakeLocation("uniform2[2]"); 526 info = program->GetUniformInfoByFakeLocation( 527 loc, &real_location, &array_index); 528 ASSERT_TRUE(info != NULL); 529 EXPECT_EQ(kUniform2RealLocation + 2 * 2, real_location); 530 EXPECT_EQ(2, array_index); 531 } 532 533 // Some GL drivers incorrectly return gl_DepthRange and possibly other uniforms 534 // that start with "gl_". Our implementation catches these and does not allow 535 // them back to client. 536 TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) { 537 static const char* kUniform2Name = "gl_longNameWeCanCheckFor"; 538 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 539 { kUniform1Name, 540 kUniform1Size, 541 kUniform1Type, 542 kUniform1FakeLocation, 543 kUniform1RealLocation, 544 kUniform1DesiredLocation, 545 kUniform1Name, 546 }, 547 { kUniform2Name, 548 kUniform2Size, 549 kUniform2Type, 550 kUniform2FakeLocation, 551 kUniform2RealLocation, 552 kUniform2DesiredLocation, 553 kUniform2Name, 554 }, 555 { kUniform3BadName, 556 kUniform3Size, 557 kUniform3Type, 558 kUniform3FakeLocation, 559 kUniform3RealLocation, 560 kUniform3DesiredLocation, 561 kUniform3GoodName, 562 }, 563 }; 564 const size_t kNumUniforms = arraysize(kUniforms); 565 static const GLuint kClientProgramId = 1234; 566 static const GLuint kServiceProgramId = 5679; 567 const GLuint kVShaderClientId = 2001; 568 const GLuint kFShaderClientId = 2002; 569 const GLuint kVShaderServiceId = 3001; 570 const GLuint kFShaderServiceId = 3002; 571 SetupShader( 572 kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId); 573 Shader* vshader = shader_manager_.CreateShader( 574 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 575 ASSERT_TRUE(vshader != NULL); 576 vshader->SetStatus(true, "", NULL); 577 Shader* fshader = shader_manager_.CreateShader( 578 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 579 ASSERT_TRUE(fshader != NULL); 580 fshader->SetStatus(true, "", NULL); 581 Program* program = 582 manager_.CreateProgram(kClientProgramId, kServiceProgramId); 583 ASSERT_TRUE(program != NULL); 584 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 585 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 586 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb)); 587 GLint value = 0; 588 program->GetProgramiv(GL_ACTIVE_ATTRIBUTES, &value); 589 EXPECT_EQ(3, value); 590 // Check that we skipped the "gl_" uniform. 591 program->GetProgramiv(GL_ACTIVE_UNIFORMS, &value); 592 EXPECT_EQ(2, value); 593 // Check that our max length adds room for the array spec and is not as long 594 // as the "gl_" uniform we skipped. 595 // +4u is to account for "gl_" and NULL terminator. 596 program->GetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH, &value); 597 EXPECT_EQ(strlen(kUniform3BadName) + 4u, static_cast<size_t>(value)); 598 } 599 600 // Test the bug comparing similar array names is fixed. 601 TEST_F(ProgramManagerWithShaderTest, SimilarArrayNames) { 602 static const char* kUniform2Name = "u_nameLong[0]"; 603 static const char* kUniform3Name = "u_name[0]"; 604 static const GLint kUniform2Size = 2; 605 static const GLint kUniform3Size = 2; 606 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 607 { kUniform1Name, 608 kUniform1Size, 609 kUniform1Type, 610 kUniform1FakeLocation, 611 kUniform1RealLocation, 612 kUniform1DesiredLocation, 613 kUniform1Name, 614 }, 615 { kUniform2Name, 616 kUniform2Size, 617 kUniform2Type, 618 kUniform2FakeLocation, 619 kUniform2RealLocation, 620 kUniform2DesiredLocation, 621 kUniform2Name, 622 }, 623 { kUniform3Name, 624 kUniform3Size, 625 kUniform3Type, 626 kUniform3FakeLocation, 627 kUniform3RealLocation, 628 kUniform3DesiredLocation, 629 kUniform3Name, 630 }, 631 }; 632 const size_t kNumUniforms = arraysize(kUniforms); 633 static const GLuint kClientProgramId = 1234; 634 static const GLuint kServiceProgramId = 5679; 635 const GLuint kVShaderClientId = 2001; 636 const GLuint kFShaderClientId = 2002; 637 const GLuint kVShaderServiceId = 3001; 638 const GLuint kFShaderServiceId = 3002; 639 SetupShader( 640 kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId); 641 Shader* vshader = shader_manager_.CreateShader( 642 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 643 ASSERT_TRUE(vshader != NULL); 644 vshader->SetStatus(true, "", NULL); 645 Shader* fshader = shader_manager_.CreateShader( 646 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 647 ASSERT_TRUE(fshader != NULL); 648 fshader->SetStatus(true, "", NULL); 649 Program* program = 650 manager_.CreateProgram(kClientProgramId, kServiceProgramId); 651 ASSERT_TRUE(program != NULL); 652 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 653 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 654 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb)); 655 656 // Check that we get the correct locations. 657 EXPECT_EQ(kUniform2FakeLocation, 658 program->GetUniformFakeLocation(kUniform2Name)); 659 EXPECT_EQ(kUniform3FakeLocation, 660 program->GetUniformFakeLocation(kUniform3Name)); 661 } 662 663 // Some GL drivers incorrectly return the wrong type. For example they return 664 // GL_FLOAT_VEC2 when they should return GL_FLOAT_MAT2. Check we handle this. 665 TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) { 666 static GLenum kAttrib2BadType = GL_FLOAT_VEC2; 667 static GLenum kAttrib2GoodType = GL_FLOAT_MAT2; 668 static GLenum kUniform2BadType = GL_FLOAT_VEC3; 669 static GLenum kUniform2GoodType = GL_FLOAT_MAT3; 670 MockShaderTranslator shader_translator; 671 ShaderTranslator::VariableMap attrib_map; 672 ShaderTranslator::VariableMap uniform_map; 673 attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo( 674 kAttrib1Type, kAttrib1Size, kAttrib1Name); 675 attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo( 676 kAttrib2GoodType, kAttrib2Size, kAttrib2Name); 677 attrib_map[kAttrib3Name] = ShaderTranslatorInterface::VariableInfo( 678 kAttrib3Type, kAttrib3Size, kAttrib3Name); 679 uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo( 680 kUniform1Type, kUniform1Size, kUniform1Name); 681 uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo( 682 kUniform2GoodType, kUniform2Size, kUniform2Name); 683 uniform_map[kUniform3GoodName] = ShaderTranslatorInterface::VariableInfo( 684 kUniform3Type, kUniform3Size, kUniform3GoodName); 685 EXPECT_CALL(shader_translator, attrib_map()) 686 .WillRepeatedly(ReturnRef(attrib_map)); 687 EXPECT_CALL(shader_translator, uniform_map()) 688 .WillRepeatedly(ReturnRef(uniform_map)); 689 ShaderTranslator::NameMap name_map; 690 EXPECT_CALL(shader_translator, name_map()) 691 .WillRepeatedly(ReturnRef(name_map)); 692 const GLuint kVShaderClientId = 2001; 693 const GLuint kFShaderClientId = 2002; 694 const GLuint kVShaderServiceId = 3001; 695 const GLuint kFShaderServiceId = 3002; 696 Shader* vshader = shader_manager_.CreateShader( 697 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 698 ASSERT_TRUE(vshader != NULL); 699 vshader->SetStatus(true, "", &shader_translator); 700 Shader* fshader = shader_manager_.CreateShader( 701 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 702 ASSERT_TRUE(fshader != NULL); 703 fshader->SetStatus(true, "", &shader_translator); 704 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = { 705 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, 706 { kAttrib2Name, kAttrib2Size, kAttrib2BadType, kAttrib2Location, }, 707 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, 708 }; 709 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 710 { kUniform1Name, 711 kUniform1Size, 712 kUniform1Type, 713 kUniform1FakeLocation, 714 kUniform1RealLocation, 715 kUniform1DesiredLocation, 716 kUniform1Name, 717 }, 718 { kUniform2Name, 719 kUniform2Size, 720 kUniform2BadType, 721 kUniform2FakeLocation, 722 kUniform2RealLocation, 723 kUniform2DesiredLocation, 724 kUniform2Name, 725 }, 726 { kUniform3BadName, 727 kUniform3Size, 728 kUniform3Type, 729 kUniform3FakeLocation, 730 kUniform3RealLocation, 731 kUniform3DesiredLocation, 732 kUniform3GoodName, 733 }, 734 }; 735 const size_t kNumAttribs= arraysize(kAttribs); 736 const size_t kNumUniforms = arraysize(kUniforms); 737 static const GLuint kClientProgramId = 1234; 738 static const GLuint kServiceProgramId = 5679; 739 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 740 kServiceProgramId); 741 Program* program = manager_.CreateProgram( 742 kClientProgramId, kServiceProgramId); 743 ASSERT_TRUE(program!= NULL); 744 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 745 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 746 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb)); 747 // Check that we got the good type, not the bad. 748 // Check Attribs 749 for (unsigned index = 0; index < kNumAttribs; ++index) { 750 const Program::VertexAttrib* attrib_info = 751 program->GetAttribInfo(index); 752 ASSERT_TRUE(attrib_info != NULL); 753 ShaderTranslator::VariableMap::const_iterator it = attrib_map.find( 754 attrib_info->name); 755 ASSERT_TRUE(it != attrib_map.end()); 756 EXPECT_EQ(it->first, attrib_info->name); 757 EXPECT_EQ(static_cast<GLenum>(it->second.type), attrib_info->type); 758 EXPECT_EQ(it->second.size, attrib_info->size); 759 EXPECT_EQ(it->second.name, attrib_info->name); 760 } 761 // Check Uniforms 762 for (unsigned index = 0; index < kNumUniforms; ++index) { 763 const Program::UniformInfo* uniform_info = 764 program->GetUniformInfo(index); 765 ASSERT_TRUE(uniform_info != NULL); 766 ShaderTranslator::VariableMap::const_iterator it = uniform_map.find( 767 uniform_info->name); 768 ASSERT_TRUE(it != uniform_map.end()); 769 EXPECT_EQ(it->first, uniform_info->name); 770 EXPECT_EQ(static_cast<GLenum>(it->second.type), uniform_info->type); 771 EXPECT_EQ(it->second.size, uniform_info->size); 772 EXPECT_EQ(it->second.name, uniform_info->name); 773 } 774 } 775 776 TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount) { 777 static const GLuint kClientProgramId = 124; 778 static const GLuint kServiceProgramId = 457; 779 Program* program = manager_.CreateProgram( 780 kClientProgramId, kServiceProgramId); 781 ASSERT_TRUE(program != NULL); 782 EXPECT_FALSE(program->CanLink()); 783 const GLuint kVShaderClientId = 2001; 784 const GLuint kFShaderClientId = 2002; 785 const GLuint kVShaderServiceId = 3001; 786 const GLuint kFShaderServiceId = 3002; 787 Shader* vshader = shader_manager_.CreateShader( 788 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 789 ASSERT_TRUE(vshader != NULL); 790 vshader->SetStatus(true, "", NULL); 791 Shader* fshader = shader_manager_.CreateShader( 792 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 793 ASSERT_TRUE(fshader != NULL); 794 fshader->SetStatus(true, "", NULL); 795 EXPECT_FALSE(vshader->InUse()); 796 EXPECT_FALSE(fshader->InUse()); 797 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 798 EXPECT_TRUE(vshader->InUse()); 799 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 800 EXPECT_TRUE(fshader->InUse()); 801 EXPECT_TRUE(program->CanLink()); 802 EXPECT_FALSE(program->InUse()); 803 EXPECT_FALSE(program->IsDeleted()); 804 manager_.UseProgram(program); 805 EXPECT_TRUE(program->InUse()); 806 manager_.UseProgram(program); 807 EXPECT_TRUE(program->InUse()); 808 manager_.MarkAsDeleted(&shader_manager_, program); 809 EXPECT_TRUE(program->IsDeleted()); 810 Program* info2 = manager_.GetProgram(kClientProgramId); 811 EXPECT_EQ(program, info2); 812 manager_.UnuseProgram(&shader_manager_, program); 813 EXPECT_TRUE(program->InUse()); 814 // this should delete the info. 815 EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)) 816 .Times(1) 817 .RetiresOnSaturation(); 818 manager_.UnuseProgram(&shader_manager_, program); 819 info2 = manager_.GetProgram(kClientProgramId); 820 EXPECT_TRUE(info2 == NULL); 821 EXPECT_FALSE(vshader->InUse()); 822 EXPECT_FALSE(fshader->InUse()); 823 } 824 825 TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount2) { 826 static const GLuint kClientProgramId = 124; 827 static const GLuint kServiceProgramId = 457; 828 Program* program = manager_.CreateProgram( 829 kClientProgramId, kServiceProgramId); 830 ASSERT_TRUE(program != NULL); 831 EXPECT_FALSE(program->CanLink()); 832 const GLuint kVShaderClientId = 2001; 833 const GLuint kFShaderClientId = 2002; 834 const GLuint kVShaderServiceId = 3001; 835 const GLuint kFShaderServiceId = 3002; 836 Shader* vshader = shader_manager_.CreateShader( 837 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 838 ASSERT_TRUE(vshader != NULL); 839 vshader->SetStatus(true, "", NULL); 840 Shader* fshader = shader_manager_.CreateShader( 841 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 842 ASSERT_TRUE(fshader != NULL); 843 fshader->SetStatus(true, "", NULL); 844 EXPECT_FALSE(vshader->InUse()); 845 EXPECT_FALSE(fshader->InUse()); 846 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 847 EXPECT_TRUE(vshader->InUse()); 848 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 849 EXPECT_TRUE(fshader->InUse()); 850 EXPECT_TRUE(program->CanLink()); 851 EXPECT_FALSE(program->InUse()); 852 EXPECT_FALSE(program->IsDeleted()); 853 manager_.UseProgram(program); 854 EXPECT_TRUE(program->InUse()); 855 manager_.UseProgram(program); 856 EXPECT_TRUE(program->InUse()); 857 manager_.UnuseProgram(&shader_manager_, program); 858 EXPECT_TRUE(program->InUse()); 859 manager_.UnuseProgram(&shader_manager_, program); 860 EXPECT_FALSE(program->InUse()); 861 Program* info2 = manager_.GetProgram(kClientProgramId); 862 EXPECT_EQ(program, info2); 863 // this should delete the program. 864 EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)) 865 .Times(1) 866 .RetiresOnSaturation(); 867 manager_.MarkAsDeleted(&shader_manager_, program); 868 info2 = manager_.GetProgram(kClientProgramId); 869 EXPECT_TRUE(info2 == NULL); 870 EXPECT_FALSE(vshader->InUse()); 871 EXPECT_FALSE(fshader->InUse()); 872 } 873 874 TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetProgramInfo) { 875 CommonDecoder::Bucket bucket; 876 const Program* program = manager_.GetProgram(kClientProgramId); 877 ASSERT_TRUE(program != NULL); 878 program->GetProgramInfo(&manager_, &bucket); 879 ProgramInfoHeader* header = 880 bucket.GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader)); 881 ASSERT_TRUE(header != NULL); 882 EXPECT_EQ(1u, header->link_status); 883 EXPECT_EQ(arraysize(kAttribs), header->num_attribs); 884 EXPECT_EQ(arraysize(kUniforms), header->num_uniforms); 885 const ProgramInput* inputs = bucket.GetDataAs<const ProgramInput*>( 886 sizeof(*header), 887 sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms)); 888 ASSERT_TRUE(inputs != NULL); 889 const ProgramInput* input = inputs; 890 // TODO(gman): Don't assume these are in order. 891 for (uint32 ii = 0; ii < header->num_attribs; ++ii) { 892 const AttribInfo& expected = kAttribs[ii]; 893 EXPECT_EQ(expected.size, input->size); 894 EXPECT_EQ(expected.type, input->type); 895 const int32* location = bucket.GetDataAs<const int32*>( 896 input->location_offset, sizeof(int32)); 897 ASSERT_TRUE(location != NULL); 898 EXPECT_EQ(expected.location, *location); 899 const char* name_buf = bucket.GetDataAs<const char*>( 900 input->name_offset, input->name_length); 901 ASSERT_TRUE(name_buf != NULL); 902 std::string name(name_buf, input->name_length); 903 EXPECT_STREQ(expected.name, name.c_str()); 904 ++input; 905 } 906 // TODO(gman): Don't assume these are in order. 907 for (uint32 ii = 0; ii < header->num_uniforms; ++ii) { 908 const UniformInfo& expected = kUniforms[ii]; 909 EXPECT_EQ(expected.size, input->size); 910 EXPECT_EQ(expected.type, input->type); 911 const int32* locations = bucket.GetDataAs<const int32*>( 912 input->location_offset, sizeof(int32) * input->size); 913 ASSERT_TRUE(locations != NULL); 914 for (int32 jj = 0; jj < input->size; ++jj) { 915 EXPECT_EQ( 916 ProgramManager::MakeFakeLocation(expected.fake_location, jj), 917 locations[jj]); 918 } 919 const char* name_buf = bucket.GetDataAs<const char*>( 920 input->name_offset, input->name_length); 921 ASSERT_TRUE(name_buf != NULL); 922 std::string name(name_buf, input->name_length); 923 EXPECT_STREQ(expected.good_name, name.c_str()); 924 ++input; 925 } 926 EXPECT_EQ(header->num_attribs + header->num_uniforms, 927 static_cast<uint32>(input - inputs)); 928 } 929 930 TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) { 931 // Set up shader 932 const GLuint kVShaderClientId = 1; 933 const GLuint kVShaderServiceId = 11; 934 const GLuint kFShaderClientId = 2; 935 const GLuint kFShaderServiceId = 12; 936 MockShaderTranslator shader_translator; 937 ShaderTranslator::VariableMap attrib_map; 938 for (uint32 ii = 0; ii < kNumAttribs; ++ii) { 939 attrib_map[kAttribs[ii].name] = ShaderTranslatorInterface::VariableInfo( 940 kAttribs[ii].type, kAttribs[ii].size, kAttribs[ii].name); 941 } 942 ShaderTranslator::VariableMap uniform_map; 943 EXPECT_CALL(shader_translator, attrib_map()) 944 .WillRepeatedly(ReturnRef(attrib_map)); 945 EXPECT_CALL(shader_translator, uniform_map()) 946 .WillRepeatedly(ReturnRef(uniform_map)); 947 ShaderTranslator::NameMap name_map; 948 EXPECT_CALL(shader_translator, name_map()) 949 .WillRepeatedly(ReturnRef(name_map)); 950 // Check we can create shader. 951 Shader* vshader = shader_manager_.CreateShader( 952 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 953 Shader* fshader = shader_manager_.CreateShader( 954 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 955 // Check shader got created. 956 ASSERT_TRUE(vshader != NULL && fshader != NULL); 957 // Set Status 958 vshader->SetStatus(true, "", &shader_translator); 959 // Check attrib infos got copied. 960 for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin(); 961 it != attrib_map.end(); ++it) { 962 const Shader::VariableInfo* variable_info = 963 vshader->GetAttribInfo(it->first); 964 ASSERT_TRUE(variable_info != NULL); 965 EXPECT_EQ(it->second.type, variable_info->type); 966 EXPECT_EQ(it->second.size, variable_info->size); 967 EXPECT_EQ(it->second.name, variable_info->name); 968 } 969 fshader->SetStatus(true, "", NULL); 970 971 // Set up program 972 const GLuint kClientProgramId = 6666; 973 const GLuint kServiceProgramId = 8888; 974 Program* program = 975 manager_.CreateProgram(kClientProgramId, kServiceProgramId); 976 ASSERT_TRUE(program != NULL); 977 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 978 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 979 980 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts()); 981 EXPECT_TRUE(LinkAsExpected(program, true)); 982 983 program->SetAttribLocationBinding(kAttrib1Name, 0); 984 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts()); 985 EXPECT_TRUE(LinkAsExpected(program, true)); 986 987 program->SetAttribLocationBinding("xxx", 0); 988 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts()); 989 EXPECT_TRUE(LinkAsExpected(program, true)); 990 991 program->SetAttribLocationBinding(kAttrib2Name, 1); 992 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts()); 993 EXPECT_TRUE(LinkAsExpected(program, true)); 994 995 program->SetAttribLocationBinding(kAttrib2Name, 0); 996 EXPECT_TRUE(program->DetectAttribLocationBindingConflicts()); 997 EXPECT_TRUE(LinkAsExpected(program, false)); 998 } 999 1000 TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) { 1001 const GLuint kVShaderClientId = 2001; 1002 const GLuint kFShaderClientId = 2002; 1003 const GLuint kVShaderServiceId = 3001; 1004 const GLuint kFShaderServiceId = 3002; 1005 Shader* vshader = shader_manager_.CreateShader( 1006 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 1007 ASSERT_TRUE(vshader != NULL); 1008 vshader->SetStatus(true, NULL, NULL); 1009 Shader* fshader = shader_manager_.CreateShader( 1010 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 1011 ASSERT_TRUE(fshader != NULL); 1012 fshader->SetStatus(true, NULL, NULL); 1013 static const GLuint kClientProgramId = 1234; 1014 static const GLuint kServiceProgramId = 5679; 1015 Program* program = manager_.CreateProgram( 1016 kClientProgramId, kServiceProgramId); 1017 ASSERT_TRUE(program != NULL); 1018 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 1019 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 1020 1021 static const GLenum kSamplerTypes[] = { 1022 GL_SAMPLER_2D, 1023 GL_SAMPLER_CUBE, 1024 GL_SAMPLER_EXTERNAL_OES, 1025 GL_SAMPLER_3D_OES, 1026 GL_SAMPLER_2D_RECT_ARB, 1027 }; 1028 const size_t kNumSamplerTypes = arraysize(kSamplerTypes); 1029 for (size_t ii = 0; ii < kNumSamplerTypes; ++ii) { 1030 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = { 1031 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, 1032 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, 1033 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, 1034 }; 1035 ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 1036 { kUniform1Name, 1037 kUniform1Size, 1038 kUniform1Type, 1039 kUniform1FakeLocation, 1040 kUniform1RealLocation, 1041 kUniform1DesiredLocation, 1042 kUniform1Name, 1043 }, 1044 { kUniform2Name, 1045 kUniform2Size, 1046 kSamplerTypes[ii], 1047 kUniform2FakeLocation, 1048 kUniform2RealLocation, 1049 kUniform2DesiredLocation, 1050 kUniform2Name, 1051 }, 1052 { kUniform3BadName, 1053 kUniform3Size, 1054 kUniform3Type, 1055 kUniform3FakeLocation, 1056 kUniform3RealLocation, 1057 kUniform3DesiredLocation, 1058 kUniform3GoodName, 1059 }, 1060 }; 1061 const size_t kNumAttribs = arraysize(kAttribs); 1062 const size_t kNumUniforms = arraysize(kUniforms); 1063 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 1064 kServiceProgramId); 1065 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb)); 1066 SetupExpectationsForClearingUniforms(kUniforms, kNumUniforms); 1067 manager_.ClearUniforms(program); 1068 } 1069 } 1070 1071 TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) { 1072 const GLuint kVShaderClientId = 2001; 1073 const GLuint kFShaderClientId = 2002; 1074 const GLuint kVShaderServiceId = 3001; 1075 const GLuint kFShaderServiceId = 3002; 1076 1077 const GLint kUniform1DesiredLocation = 10; 1078 const GLint kUniform2DesiredLocation = -1; 1079 const GLint kUniform3DesiredLocation = 5; 1080 1081 Shader* vshader = shader_manager_.CreateShader( 1082 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); 1083 ASSERT_TRUE(vshader != NULL); 1084 vshader->SetStatus(true, NULL, NULL); 1085 Shader* fshader = shader_manager_.CreateShader( 1086 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); 1087 ASSERT_TRUE(fshader != NULL); 1088 fshader->SetStatus(true, NULL, NULL); 1089 static const GLuint kClientProgramId = 1234; 1090 static const GLuint kServiceProgramId = 5679; 1091 Program* program = manager_.CreateProgram( 1092 kClientProgramId, kServiceProgramId); 1093 ASSERT_TRUE(program != NULL); 1094 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); 1095 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); 1096 EXPECT_TRUE(program->SetUniformLocationBinding( 1097 kUniform1Name, kUniform1DesiredLocation)); 1098 EXPECT_TRUE(program->SetUniformLocationBinding( 1099 kUniform3BadName, kUniform3DesiredLocation)); 1100 1101 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = { 1102 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, 1103 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, 1104 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, 1105 }; 1106 ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { 1107 { kUniform1Name, 1108 kUniform1Size, 1109 kUniform1Type, 1110 kUniform1FakeLocation, 1111 kUniform1RealLocation, 1112 kUniform1DesiredLocation, 1113 kUniform1Name, 1114 }, 1115 { kUniform2Name, 1116 kUniform2Size, 1117 kUniform2Type, 1118 kUniform2FakeLocation, 1119 kUniform2RealLocation, 1120 kUniform2DesiredLocation, 1121 kUniform2Name, 1122 }, 1123 { kUniform3BadName, 1124 kUniform3Size, 1125 kUniform3Type, 1126 kUniform3FakeLocation, 1127 kUniform3RealLocation, 1128 kUniform3DesiredLocation, 1129 kUniform3GoodName, 1130 }, 1131 }; 1132 1133 const size_t kNumAttribs = arraysize(kAttribs); 1134 const size_t kNumUniforms = arraysize(kUniforms); 1135 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, 1136 kServiceProgramId); 1137 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb)); 1138 1139 EXPECT_EQ(kUniform1DesiredLocation, 1140 program->GetUniformFakeLocation(kUniform1Name)); 1141 EXPECT_EQ(kUniform3DesiredLocation, 1142 program->GetUniformFakeLocation(kUniform3BadName)); 1143 EXPECT_EQ(kUniform3DesiredLocation, 1144 program->GetUniformFakeLocation(kUniform3GoodName)); 1145 } 1146 1147 class ProgramManagerWithCacheTest : public testing::Test { 1148 public: 1149 static const GLuint kClientProgramId = 1; 1150 static const GLuint kServiceProgramId = 10; 1151 static const GLuint kVertexShaderClientId = 2; 1152 static const GLuint kFragmentShaderClientId = 20; 1153 static const GLuint kVertexShaderServiceId = 3; 1154 static const GLuint kFragmentShaderServiceId = 30; 1155 1156 ProgramManagerWithCacheTest() 1157 : cache_(new MockProgramCache()), 1158 manager_(cache_.get()), 1159 vertex_shader_(NULL), 1160 fragment_shader_(NULL), 1161 program_(NULL) { 1162 } 1163 virtual ~ProgramManagerWithCacheTest() { 1164 manager_.Destroy(false); 1165 shader_manager_.Destroy(false); 1166 } 1167 1168 protected: 1169 virtual void SetUp() { 1170 gl_.reset(new StrictMock<gfx::MockGLInterface>()); 1171 ::gfx::GLInterface::SetGLInterface(gl_.get()); 1172 1173 vertex_shader_ = shader_manager_.CreateShader( 1174 kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER); 1175 fragment_shader_ = shader_manager_.CreateShader( 1176 kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER); 1177 ASSERT_TRUE(vertex_shader_ != NULL); 1178 ASSERT_TRUE(fragment_shader_ != NULL); 1179 vertex_shader_->UpdateSource("lka asjf bjajsdfj"); 1180 fragment_shader_->UpdateSource("lka asjf a fasgag 3rdsf3 bjajsdfj"); 1181 1182 program_ = manager_.CreateProgram( 1183 kClientProgramId, kServiceProgramId); 1184 ASSERT_TRUE(program_ != NULL); 1185 1186 program_->AttachShader(&shader_manager_, vertex_shader_); 1187 program_->AttachShader(&shader_manager_, fragment_shader_); 1188 } 1189 1190 virtual void TearDown() { 1191 ::gfx::GLInterface::SetGLInterface(NULL); 1192 } 1193 1194 void SetShadersCompiled() { 1195 vertex_shader_->SetStatus(true, NULL, NULL); 1196 fragment_shader_->SetStatus(true, NULL, NULL); 1197 } 1198 1199 void SetProgramCached() { 1200 cache_->LinkedProgramCacheSuccess( 1201 vertex_shader_->source()->c_str(), 1202 NULL, 1203 fragment_shader_->source()->c_str(), 1204 NULL, 1205 &program_->bind_attrib_location_map()); 1206 } 1207 1208 void SetExpectationsForProgramCached() { 1209 SetExpectationsForProgramCached(program_, 1210 vertex_shader_, 1211 fragment_shader_); 1212 } 1213 1214 void SetExpectationsForProgramCached( 1215 Program* program, 1216 Shader* vertex_shader, 1217 Shader* fragment_shader) { 1218 EXPECT_CALL(*cache_.get(), SaveLinkedProgram( 1219 program->service_id(), 1220 vertex_shader, 1221 NULL, 1222 fragment_shader, 1223 NULL, 1224 &program->bind_attrib_location_map(), 1225 _)).Times(1); 1226 } 1227 1228 void SetExpectationsForNotCachingProgram() { 1229 SetExpectationsForNotCachingProgram(program_, 1230 vertex_shader_, 1231 fragment_shader_); 1232 } 1233 1234 void SetExpectationsForNotCachingProgram( 1235 Program* program, 1236 Shader* vertex_shader, 1237 Shader* fragment_shader) { 1238 EXPECT_CALL(*cache_.get(), SaveLinkedProgram( 1239 program->service_id(), 1240 vertex_shader, 1241 NULL, 1242 fragment_shader, 1243 NULL, 1244 &program->bind_attrib_location_map(), 1245 _)).Times(0); 1246 } 1247 1248 void SetExpectationsForProgramLoad(ProgramCache::ProgramLoadResult result) { 1249 SetExpectationsForProgramLoad(kServiceProgramId, 1250 program_, 1251 vertex_shader_, 1252 fragment_shader_, 1253 result); 1254 } 1255 1256 void SetExpectationsForProgramLoad( 1257 GLuint service_program_id, 1258 Program* program, 1259 Shader* vertex_shader, 1260 Shader* fragment_shader, 1261 ProgramCache::ProgramLoadResult result) { 1262 EXPECT_CALL(*cache_.get(), 1263 LoadLinkedProgram(service_program_id, 1264 vertex_shader, 1265 NULL, 1266 fragment_shader, 1267 NULL, 1268 &program->bind_attrib_location_map(), 1269 _)) 1270 .WillOnce(Return(result)); 1271 } 1272 1273 void SetExpectationsForProgramLoadSuccess() { 1274 SetExpectationsForProgramLoadSuccess(kServiceProgramId); 1275 } 1276 1277 void SetExpectationsForProgramLoadSuccess(GLuint service_program_id) { 1278 TestHelper::SetupProgramSuccessExpectations(gl_.get(), 1279 NULL, 1280 0, 1281 NULL, 1282 0, 1283 service_program_id); 1284 } 1285 1286 void SetExpectationsForProgramLink() { 1287 SetExpectationsForProgramLink(kServiceProgramId); 1288 } 1289 1290 void SetExpectationsForProgramLink(GLuint service_program_id) { 1291 TestHelper::SetupShader(gl_.get(), NULL, 0, NULL, 0, service_program_id); 1292 if (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) { 1293 EXPECT_CALL(*gl_.get(), 1294 ProgramParameteri(service_program_id, 1295 PROGRAM_BINARY_RETRIEVABLE_HINT, 1296 GL_TRUE)).Times(1); 1297 } 1298 } 1299 1300 void SetExpectationsForSuccessCompile( 1301 const Shader* shader) { 1302 const GLuint shader_id = shader->service_id(); 1303 const char* src = shader->source()->c_str(); 1304 EXPECT_CALL(*gl_.get(), 1305 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); 1306 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); 1307 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) 1308 .WillOnce(SetArgumentPointee<2>(GL_TRUE)); 1309 } 1310 1311 void SetExpectationsForNoCompile(const Shader* shader) { 1312 const GLuint shader_id = shader->service_id(); 1313 const char* src = shader->source()->c_str(); 1314 EXPECT_CALL(*gl_.get(), 1315 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); 1316 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); 1317 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) 1318 .Times(0); 1319 } 1320 1321 void SetExpectationsForErrorCompile(const Shader* shader) { 1322 const GLuint shader_id = shader->service_id(); 1323 const char* src = shader->source()->c_str(); 1324 EXPECT_CALL(*gl_.get(), 1325 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); 1326 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); 1327 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) 1328 .WillOnce(SetArgumentPointee<2>(GL_FALSE)); 1329 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) 1330 .WillOnce(SetArgumentPointee<2>(0)); 1331 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) 1332 .Times(1); 1333 } 1334 1335 scoped_ptr<StrictMock<gfx::MockGLInterface> > gl_; 1336 1337 scoped_ptr<MockProgramCache> cache_; 1338 ProgramManager manager_; 1339 1340 Shader* vertex_shader_; 1341 Shader* fragment_shader_; 1342 Program* program_; 1343 ShaderManager shader_manager_; 1344 }; 1345 1346 // GCC requires these declarations, but MSVC requires they not be present 1347 #ifndef COMPILER_MSVC 1348 const GLuint ProgramManagerWithCacheTest::kClientProgramId; 1349 const GLuint ProgramManagerWithCacheTest::kServiceProgramId; 1350 const GLuint ProgramManagerWithCacheTest::kVertexShaderClientId; 1351 const GLuint ProgramManagerWithCacheTest::kFragmentShaderClientId; 1352 const GLuint ProgramManagerWithCacheTest::kVertexShaderServiceId; 1353 const GLuint ProgramManagerWithCacheTest::kFragmentShaderServiceId; 1354 #endif 1355 1356 TEST_F(ProgramManagerWithCacheTest, CacheProgramOnSuccessfulLink) { 1357 SetShadersCompiled(); 1358 SetExpectationsForProgramLink(); 1359 SetExpectationsForProgramCached(); 1360 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, NULL, 1361 base::Bind(&ShaderCacheCb))); 1362 } 1363 1364 TEST_F(ProgramManagerWithCacheTest, LoadProgramOnProgramCacheHit) { 1365 SetShadersCompiled(); 1366 SetProgramCached(); 1367 1368 SetExpectationsForNoCompile(vertex_shader_); 1369 SetExpectationsForNoCompile(fragment_shader_); 1370 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); 1371 SetExpectationsForNotCachingProgram(); 1372 SetExpectationsForProgramLoadSuccess(); 1373 1374 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, NULL, 1375 base::Bind(&ShaderCacheCb))); 1376 } 1377 1378 } // namespace gles2 1379 } // namespace gpu 1380