Home | History | Annotate | Download | only in service
      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