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/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