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/memory_program_cache.h" 6 7 #include "base/bind.h" 8 #include "gpu/command_buffer/common/gles2_cmd_format.h" 9 #include "gpu/command_buffer/service/gl_utils.h" 10 #include "gpu/command_buffer/service/shader_manager.h" 11 #include "gpu/command_buffer/service/shader_translator.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "ui/gl/gl_bindings.h" 14 #include "ui/gl/gl_mock.h" 15 16 using ::testing::_; 17 using ::testing::ElementsAreArray; 18 using ::testing::Invoke; 19 using ::testing::SetArgPointee; 20 using ::testing::SetArrayArgument; 21 22 namespace { 23 typedef gpu::gles2::ShaderTranslator::VariableMap VariableMap; 24 } // anonymous namespace 25 26 namespace gpu { 27 namespace gles2 { 28 29 class ProgramBinaryEmulator { 30 public: 31 ProgramBinaryEmulator(GLsizei length, 32 GLenum format, 33 const char* binary) 34 : length_(length), 35 format_(format), 36 binary_(binary) { } 37 38 void GetProgramBinary(GLuint program, 39 GLsizei buffer_size, 40 GLsizei* length, 41 GLenum* format, 42 GLvoid* binary) { 43 if (length) { 44 *length = length_; 45 } 46 *format = format_; 47 memcpy(binary, binary_, length_); 48 } 49 50 void ProgramBinary(GLuint program, 51 GLenum format, 52 const GLvoid* binary, 53 GLsizei length) { 54 // format and length are verified by matcher 55 EXPECT_EQ(0, memcmp(binary_, binary, length)); 56 } 57 58 GLsizei length() const { return length_; } 59 GLenum format() const { return format_; } 60 const char* binary() const { return binary_; } 61 62 private: 63 GLsizei length_; 64 GLenum format_; 65 const char* binary_; 66 }; 67 68 class MemoryProgramCacheTest : public testing::Test { 69 public: 70 static const size_t kCacheSizeBytes = 1024; 71 static const GLuint kVertexShaderClientId = 90; 72 static const GLuint kVertexShaderServiceId = 100; 73 static const GLuint kFragmentShaderClientId = 91; 74 static const GLuint kFragmentShaderServiceId = 100; 75 76 MemoryProgramCacheTest() 77 : cache_(new MemoryProgramCache(kCacheSizeBytes)), 78 vertex_shader_(NULL), 79 fragment_shader_(NULL), 80 shader_cache_count_(0) { } 81 virtual ~MemoryProgramCacheTest() { 82 shader_manager_.Destroy(false); 83 } 84 85 void ShaderCacheCb(const std::string& key, const std::string& shader) { 86 shader_cache_count_++; 87 shader_cache_shader_ = shader; 88 } 89 90 int32 shader_cache_count() { return shader_cache_count_; } 91 const std::string& shader_cache_shader() { return shader_cache_shader_; } 92 93 protected: 94 virtual void SetUp() { 95 gl_.reset(new ::testing::StrictMock<gfx::MockGLInterface>()); 96 ::gfx::GLInterface::SetGLInterface(gl_.get()); 97 98 vertex_shader_ = shader_manager_.CreateShader(kVertexShaderClientId, 99 kVertexShaderServiceId, 100 GL_VERTEX_SHADER); 101 fragment_shader_ = shader_manager_.CreateShader( 102 kFragmentShaderClientId, 103 kFragmentShaderServiceId, 104 GL_FRAGMENT_SHADER); 105 ASSERT_TRUE(vertex_shader_ != NULL); 106 ASSERT_TRUE(fragment_shader_ != NULL); 107 typedef ShaderTranslatorInterface::VariableInfo VariableInfo; 108 typedef ShaderTranslator::VariableMap VariableMap; 109 VariableMap vertex_attrib_map; 110 VariableMap vertex_uniform_map; 111 VariableMap fragment_attrib_map; 112 VariableMap fragment_uniform_map; 113 114 vertex_attrib_map["a"] = VariableInfo(1, 34, "a"); 115 vertex_uniform_map["a"] = VariableInfo(0, 10, "a"); 116 vertex_uniform_map["b"] = VariableInfo(2, 3114, "b"); 117 fragment_attrib_map["jjjbb"] = VariableInfo(463, 1114, "jjjbb"); 118 fragment_uniform_map["k"] = VariableInfo(10, 34413, "k"); 119 120 vertex_shader_->set_attrib_map(vertex_attrib_map); 121 vertex_shader_->set_uniform_map(vertex_uniform_map); 122 fragment_shader_->set_attrib_map(vertex_attrib_map); 123 fragment_shader_->set_uniform_map(vertex_uniform_map); 124 125 vertex_shader_->UpdateSource("bbbalsldkdkdkd"); 126 fragment_shader_->UpdateSource("bbbal sldkdkdkas 134 ad"); 127 128 vertex_shader_->SetStatus(true, NULL, NULL); 129 fragment_shader_->SetStatus(true, NULL, NULL); 130 } 131 132 virtual void TearDown() { 133 ::gfx::GLInterface::SetGLInterface(NULL); 134 gl_.reset(); 135 } 136 137 void SetExpectationsForSaveLinkedProgram( 138 const GLint program_id, 139 ProgramBinaryEmulator* emulator) const { 140 EXPECT_CALL(*gl_.get(), 141 GetProgramiv(program_id, GL_PROGRAM_BINARY_LENGTH_OES, _)) 142 .WillOnce(SetArgPointee<2>(emulator->length())); 143 EXPECT_CALL(*gl_.get(), 144 GetProgramBinary(program_id, emulator->length(), _, _, _)) 145 .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::GetProgramBinary)); 146 } 147 148 void SetExpectationsForLoadLinkedProgram( 149 const GLint program_id, 150 ProgramBinaryEmulator* emulator) const { 151 EXPECT_CALL(*gl_.get(), 152 ProgramBinary(program_id, 153 emulator->format(), 154 _, 155 emulator->length())) 156 .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::ProgramBinary)); 157 EXPECT_CALL(*gl_.get(), 158 GetProgramiv(program_id, GL_LINK_STATUS, _)) 159 .WillOnce(SetArgPointee<2>(GL_TRUE)); 160 } 161 162 void SetExpectationsForLoadLinkedProgramFailure( 163 const GLint program_id, 164 ProgramBinaryEmulator* emulator) const { 165 EXPECT_CALL(*gl_.get(), 166 ProgramBinary(program_id, 167 emulator->format(), 168 _, 169 emulator->length())) 170 .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::ProgramBinary)); 171 EXPECT_CALL(*gl_.get(), 172 GetProgramiv(program_id, GL_LINK_STATUS, _)) 173 .WillOnce(SetArgPointee<2>(GL_FALSE)); 174 } 175 176 // Use StrictMock to make 100% sure we know how GL will be called. 177 scoped_ptr< ::testing::StrictMock<gfx::MockGLInterface> > gl_; 178 scoped_ptr<MemoryProgramCache> cache_; 179 ShaderManager shader_manager_; 180 Shader* vertex_shader_; 181 Shader* fragment_shader_; 182 int32 shader_cache_count_; 183 std::string shader_cache_shader_; 184 }; 185 186 TEST_F(MemoryProgramCacheTest, CacheSave) { 187 const GLenum kFormat = 1; 188 const int kProgramId = 10; 189 const int kBinaryLength = 20; 190 char test_binary[kBinaryLength]; 191 for (int i = 0; i < kBinaryLength; ++i) { 192 test_binary[i] = i; 193 } 194 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 195 196 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 197 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 198 fragment_shader_, NULL, NULL, 199 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 200 base::Unretained(this))); 201 202 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus( 203 *vertex_shader_->signature_source(), 204 NULL, 205 *fragment_shader_->signature_source(), 206 NULL, 207 NULL)); 208 EXPECT_EQ(1, shader_cache_count()); 209 } 210 211 TEST_F(MemoryProgramCacheTest, LoadProgram) { 212 const GLenum kFormat = 1; 213 const int kProgramId = 10; 214 const int kBinaryLength = 20; 215 char test_binary[kBinaryLength]; 216 for (int i = 0; i < kBinaryLength; ++i) { 217 test_binary[i] = i; 218 } 219 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 220 221 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 222 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 223 fragment_shader_, NULL, NULL, 224 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 225 base::Unretained(this))); 226 227 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus( 228 *vertex_shader_->signature_source(), 229 NULL, 230 *fragment_shader_->signature_source(), 231 NULL, 232 NULL)); 233 EXPECT_EQ(1, shader_cache_count()); 234 235 cache_->Clear(); 236 237 cache_->LoadProgram(shader_cache_shader()); 238 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus( 239 *vertex_shader_->signature_source(), 240 NULL, 241 *fragment_shader_->signature_source(), 242 NULL, 243 NULL)); 244 } 245 246 TEST_F(MemoryProgramCacheTest, CacheLoadMatchesSave) { 247 const GLenum kFormat = 1; 248 const int kProgramId = 10; 249 const int kBinaryLength = 20; 250 char test_binary[kBinaryLength]; 251 for (int i = 0; i < kBinaryLength; ++i) { 252 test_binary[i] = i; 253 } 254 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 255 256 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 257 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 258 fragment_shader_, NULL, NULL, 259 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 260 base::Unretained(this))); 261 EXPECT_EQ(1, shader_cache_count()); 262 263 VariableMap vertex_attrib_map = vertex_shader_->attrib_map(); 264 VariableMap vertex_uniform_map = vertex_shader_->uniform_map(); 265 VariableMap fragment_attrib_map = fragment_shader_->attrib_map(); 266 VariableMap fragment_uniform_map = fragment_shader_->uniform_map(); 267 268 vertex_shader_->set_attrib_map(VariableMap()); 269 vertex_shader_->set_uniform_map(VariableMap()); 270 fragment_shader_->set_attrib_map(VariableMap()); 271 fragment_shader_->set_uniform_map(VariableMap()); 272 273 SetExpectationsForLoadLinkedProgram(kProgramId, &emulator); 274 275 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram( 276 kProgramId, 277 vertex_shader_, 278 NULL, 279 fragment_shader_, 280 NULL, 281 NULL, 282 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 283 base::Unretained(this)))); 284 285 // apparently the hash_map implementation on android doesn't have the 286 // equality operator 287 #if !defined(OS_ANDROID) 288 EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map()); 289 EXPECT_EQ(vertex_attrib_map, vertex_shader_->uniform_map()); 290 EXPECT_EQ(vertex_attrib_map, fragment_shader_->attrib_map()); 291 EXPECT_EQ(vertex_attrib_map, fragment_shader_->uniform_map()); 292 #endif 293 } 294 295 TEST_F(MemoryProgramCacheTest, LoadProgramMatchesSave) { 296 const GLenum kFormat = 1; 297 const int kProgramId = 10; 298 const int kBinaryLength = 20; 299 char test_binary[kBinaryLength]; 300 for (int i = 0; i < kBinaryLength; ++i) { 301 test_binary[i] = i; 302 } 303 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 304 305 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 306 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 307 fragment_shader_, NULL, NULL, 308 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 309 base::Unretained(this))); 310 EXPECT_EQ(1, shader_cache_count()); 311 312 VariableMap vertex_attrib_map = vertex_shader_->attrib_map(); 313 VariableMap vertex_uniform_map = vertex_shader_->uniform_map(); 314 VariableMap fragment_attrib_map = fragment_shader_->attrib_map(); 315 VariableMap fragment_uniform_map = fragment_shader_->uniform_map(); 316 317 vertex_shader_->set_attrib_map(VariableMap()); 318 vertex_shader_->set_uniform_map(VariableMap()); 319 fragment_shader_->set_attrib_map(VariableMap()); 320 fragment_shader_->set_uniform_map(VariableMap()); 321 322 SetExpectationsForLoadLinkedProgram(kProgramId, &emulator); 323 324 cache_->Clear(); 325 cache_->LoadProgram(shader_cache_shader()); 326 327 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram( 328 kProgramId, 329 vertex_shader_, 330 NULL, 331 fragment_shader_, 332 NULL, 333 NULL, 334 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 335 base::Unretained(this)))); 336 337 // apparently the hash_map implementation on android doesn't have the 338 // equality operator 339 #if !defined(OS_ANDROID) 340 EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map()); 341 EXPECT_EQ(vertex_attrib_map, vertex_shader_->uniform_map()); 342 EXPECT_EQ(vertex_attrib_map, fragment_shader_->attrib_map()); 343 EXPECT_EQ(vertex_attrib_map, fragment_shader_->uniform_map()); 344 #endif 345 } 346 347 TEST_F(MemoryProgramCacheTest, LoadFailOnLinkFalse) { 348 const GLenum kFormat = 1; 349 const int kProgramId = 10; 350 const int kBinaryLength = 20; 351 char test_binary[kBinaryLength]; 352 for (int i = 0; i < kBinaryLength; ++i) { 353 test_binary[i] = i; 354 } 355 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 356 357 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 358 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 359 fragment_shader_, NULL, NULL, 360 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 361 base::Unretained(this))); 362 363 SetExpectationsForLoadLinkedProgramFailure(kProgramId, &emulator); 364 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram( 365 kProgramId, 366 vertex_shader_, 367 NULL, 368 fragment_shader_, 369 NULL, 370 NULL, 371 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 372 base::Unretained(this)))); 373 } 374 375 TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentSource) { 376 const GLenum kFormat = 1; 377 const int kProgramId = 10; 378 const int kBinaryLength = 20; 379 char test_binary[kBinaryLength]; 380 for (int i = 0; i < kBinaryLength; ++i) { 381 test_binary[i] = i; 382 } 383 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 384 385 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 386 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 387 fragment_shader_, NULL, NULL, 388 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 389 base::Unretained(this))); 390 391 const std::string vertex_orig_source = 392 *vertex_shader_->signature_source(); 393 vertex_shader_->UpdateSource("different!"); 394 vertex_shader_->SetStatus(true, NULL, NULL); 395 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram( 396 kProgramId, 397 vertex_shader_, 398 NULL, 399 fragment_shader_, 400 NULL, 401 NULL, 402 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 403 base::Unretained(this)))); 404 405 vertex_shader_->UpdateSource(vertex_orig_source.c_str()); 406 vertex_shader_->SetStatus(true, NULL, NULL); 407 fragment_shader_->UpdateSource("different!"); 408 fragment_shader_->SetStatus(true, NULL, NULL); 409 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram( 410 kProgramId, 411 vertex_shader_, 412 NULL, 413 fragment_shader_, 414 NULL, 415 NULL, 416 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 417 base::Unretained(this)))); 418 } 419 420 TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentMap) { 421 const GLenum kFormat = 1; 422 const int kProgramId = 10; 423 const int kBinaryLength = 20; 424 char test_binary[kBinaryLength]; 425 for (int i = 0; i < kBinaryLength; ++i) { 426 test_binary[i] = i; 427 } 428 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 429 430 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 431 ProgramCache::LocationMap binding_map; 432 binding_map["test"] = 512; 433 cache_->SaveLinkedProgram(kProgramId, 434 vertex_shader_, 435 NULL, 436 fragment_shader_, 437 NULL, 438 &binding_map, 439 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 440 base::Unretained(this))); 441 442 binding_map["different!"] = 59; 443 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram( 444 kProgramId, 445 vertex_shader_, 446 NULL, 447 fragment_shader_, 448 NULL, 449 &binding_map, 450 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 451 base::Unretained(this)))); 452 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram( 453 kProgramId, 454 vertex_shader_, 455 NULL, 456 fragment_shader_, 457 NULL, 458 NULL, 459 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 460 base::Unretained(this)))); 461 } 462 463 TEST_F(MemoryProgramCacheTest, MemoryProgramCacheEviction) { 464 typedef ShaderTranslator::VariableMap VariableMap; 465 const GLenum kFormat = 1; 466 const int kProgramId = 10; 467 const int kBinaryLength = 20; 468 char test_binary[kBinaryLength]; 469 for (int i = 0; i < kBinaryLength; ++i) { 470 test_binary[i] = i; 471 } 472 ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary); 473 474 475 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1); 476 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 477 fragment_shader_, NULL, NULL, 478 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 479 base::Unretained(this))); 480 481 const int kEvictingProgramId = 11; 482 const GLuint kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1; 483 484 // save old source and modify for new program 485 const std::string old_source = 486 *fragment_shader_->signature_source(); 487 fragment_shader_->UpdateSource("al sdfkjdk"); 488 fragment_shader_->SetStatus(true, NULL, NULL); 489 490 scoped_ptr<char[]> bigTestBinary = 491 scoped_ptr<char[]>(new char[kEvictingBinaryLength]); 492 for (size_t i = 0; i < kEvictingBinaryLength; ++i) { 493 bigTestBinary[i] = i % 250; 494 } 495 ProgramBinaryEmulator emulator2(kEvictingBinaryLength, 496 kFormat, 497 bigTestBinary.get()); 498 499 SetExpectationsForSaveLinkedProgram(kEvictingProgramId, &emulator2); 500 cache_->SaveLinkedProgram(kEvictingProgramId, 501 vertex_shader_, 502 NULL, 503 fragment_shader_, 504 NULL, 505 NULL, 506 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 507 base::Unretained(this))); 508 509 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus( 510 *vertex_shader_->signature_source(), 511 NULL, 512 *fragment_shader_->signature_source(), 513 NULL, 514 NULL)); 515 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus( 516 old_source, 517 NULL, 518 *fragment_shader_->signature_source(), 519 NULL, 520 NULL)); 521 } 522 523 TEST_F(MemoryProgramCacheTest, SaveCorrectProgram) { 524 const GLenum kFormat = 1; 525 const int kProgramId = 10; 526 const int kBinaryLength = 20; 527 char test_binary[kBinaryLength]; 528 for (int i = 0; i < kBinaryLength; ++i) { 529 test_binary[i] = i; 530 } 531 ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary); 532 533 vertex_shader_->UpdateSource("different!"); 534 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1); 535 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 536 fragment_shader_, NULL, NULL, 537 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 538 base::Unretained(this))); 539 540 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus( 541 *vertex_shader_->signature_source(), 542 NULL, 543 *fragment_shader_->signature_source(), 544 NULL, 545 NULL)); 546 } 547 548 TEST_F(MemoryProgramCacheTest, LoadCorrectProgram) { 549 const GLenum kFormat = 1; 550 const int kProgramId = 10; 551 const int kBinaryLength = 20; 552 char test_binary[kBinaryLength]; 553 for (int i = 0; i < kBinaryLength; ++i) { 554 test_binary[i] = i; 555 } 556 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 557 558 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 559 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 560 fragment_shader_, NULL, NULL, 561 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 562 base::Unretained(this))); 563 564 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus( 565 *vertex_shader_->signature_source(), 566 NULL, 567 *fragment_shader_->signature_source(), 568 NULL, 569 NULL)); 570 571 SetExpectationsForLoadLinkedProgram(kProgramId, &emulator); 572 573 fragment_shader_->UpdateSource("different!"); 574 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram( 575 kProgramId, 576 vertex_shader_, 577 NULL, 578 fragment_shader_, 579 NULL, 580 NULL, 581 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 582 base::Unretained(this)))); 583 } 584 585 TEST_F(MemoryProgramCacheTest, OverwriteOnNewSave) { 586 const GLenum kFormat = 1; 587 const int kProgramId = 10; 588 const int kBinaryLength = 20; 589 char test_binary[kBinaryLength]; 590 for (int i = 0; i < kBinaryLength; ++i) { 591 test_binary[i] = i; 592 } 593 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); 594 595 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); 596 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 597 fragment_shader_, NULL, NULL, 598 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 599 base::Unretained(this))); 600 601 602 char test_binary2[kBinaryLength]; 603 for (int i = 0; i < kBinaryLength; ++i) { 604 test_binary2[i] = (i*2) % 250; 605 } 606 ProgramBinaryEmulator emulator2(kBinaryLength, kFormat, test_binary2); 607 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator2); 608 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL, 609 fragment_shader_, NULL, NULL, 610 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 611 base::Unretained(this))); 612 613 SetExpectationsForLoadLinkedProgram(kProgramId, &emulator2); 614 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram( 615 kProgramId, 616 vertex_shader_, 617 NULL, 618 fragment_shader_, 619 NULL, 620 NULL, 621 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb, 622 base::Unretained(this)))); 623 } 624 625 } // namespace gles2 626 } // namespace gpu 627