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