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 "gpu/command_buffer/service/test_helper.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "ui/gl/gl_bindings.h"
     16 #include "ui/gl/gl_mock.h"
     17 
     18 using ::testing::_;
     19 using ::testing::ElementsAreArray;
     20 using ::testing::Invoke;
     21 using ::testing::SetArgPointee;
     22 using ::testing::SetArrayArgument;
     23 
     24 namespace {
     25 typedef gpu::gles2::ShaderTranslator::VariableMap VariableMap;
     26 }  // anonymous namespace
     27 
     28 namespace gpu {
     29 namespace gles2 {
     30 
     31 class ProgramBinaryEmulator {
     32  public:
     33   ProgramBinaryEmulator(GLsizei length,
     34                         GLenum format,
     35                         const char* binary)
     36       : length_(length),
     37         format_(format),
     38         binary_(binary) { }
     39 
     40   void GetProgramBinary(GLuint program,
     41                         GLsizei buffer_size,
     42                         GLsizei* length,
     43                         GLenum* format,
     44                         GLvoid* binary) {
     45     if (length) {
     46       *length = length_;
     47     }
     48     *format = format_;
     49     memcpy(binary, binary_, length_);
     50   }
     51 
     52   void ProgramBinary(GLuint program,
     53                      GLenum format,
     54                      const GLvoid* binary,
     55                      GLsizei length) {
     56     // format and length are verified by matcher
     57     EXPECT_EQ(0, memcmp(binary_, binary, length));
     58   }
     59 
     60   GLsizei length() const { return length_; }
     61   GLenum format() const { return format_; }
     62   const char* binary() const { return binary_; }
     63 
     64  private:
     65   GLsizei length_;
     66   GLenum format_;
     67   const char* binary_;
     68 };
     69 
     70 class MemoryProgramCacheTest : public GpuServiceTest {
     71  public:
     72   static const size_t kCacheSizeBytes = 1024;
     73   static const GLuint kVertexShaderClientId = 90;
     74   static const GLuint kVertexShaderServiceId = 100;
     75   static const GLuint kFragmentShaderClientId = 91;
     76   static const GLuint kFragmentShaderServiceId = 100;
     77 
     78   MemoryProgramCacheTest()
     79       : cache_(new MemoryProgramCache(kCacheSizeBytes)),
     80         vertex_shader_(NULL),
     81         fragment_shader_(NULL),
     82         shader_cache_count_(0) { }
     83   virtual ~MemoryProgramCacheTest() {
     84     shader_manager_.Destroy(false);
     85   }
     86 
     87   void ShaderCacheCb(const std::string& key, const std::string& shader) {
     88     shader_cache_count_++;
     89     shader_cache_shader_ = shader;
     90   }
     91 
     92   int32 shader_cache_count() { return shader_cache_count_; }
     93   const std::string& shader_cache_shader() { return shader_cache_shader_; }
     94 
     95  protected:
     96   virtual void SetUp() {
     97     GpuServiceTest::SetUp();
     98 
     99     vertex_shader_ = shader_manager_.CreateShader(kVertexShaderClientId,
    100                                                   kVertexShaderServiceId,
    101                                                   GL_VERTEX_SHADER);
    102     fragment_shader_ = shader_manager_.CreateShader(
    103         kFragmentShaderClientId,
    104         kFragmentShaderServiceId,
    105         GL_FRAGMENT_SHADER);
    106     ASSERT_TRUE(vertex_shader_ != NULL);
    107     ASSERT_TRUE(fragment_shader_ != NULL);
    108     typedef ShaderTranslatorInterface::VariableInfo VariableInfo;
    109     typedef ShaderTranslator::VariableMap VariableMap;
    110     VariableMap vertex_attrib_map;
    111     VariableMap vertex_uniform_map;
    112     VariableMap vertex_varying_map;
    113     VariableMap fragment_attrib_map;
    114     VariableMap fragment_uniform_map;
    115     VariableMap fragment_varying_map;
    116 
    117     vertex_attrib_map["a"] = VariableInfo(1, 34, SH_PRECISION_LOWP, 0, "a");
    118     vertex_uniform_map["a"] = VariableInfo(0, 10, SH_PRECISION_MEDIUMP, 1, "a");
    119     vertex_uniform_map["b"] = VariableInfo(2, 3114, SH_PRECISION_HIGHP, 1, "b");
    120     vertex_varying_map["c"] = VariableInfo(3, 2, SH_PRECISION_HIGHP, 1, "c");
    121     fragment_attrib_map["jjjbb"] =
    122         VariableInfo(463, 1114, SH_PRECISION_MEDIUMP, 0, "jjjbb");
    123     fragment_uniform_map["k"] =
    124         VariableInfo(10, 34413, SH_PRECISION_MEDIUMP, 1, "k");
    125     fragment_varying_map["c"] = VariableInfo(3, 2, SH_PRECISION_HIGHP, 1, "c");
    126 
    127     vertex_shader_->set_source("bbbalsldkdkdkd");
    128     fragment_shader_->set_source("bbbal   sldkdkdkas 134 ad");
    129 
    130     TestHelper::SetShaderStates(
    131         gl_.get(), vertex_shader_, true, NULL, NULL,
    132         &vertex_attrib_map, &vertex_uniform_map, &vertex_varying_map,
    133         NULL);
    134     TestHelper::SetShaderStates(
    135         gl_.get(), fragment_shader_, true, NULL, NULL,
    136         &fragment_attrib_map, &fragment_uniform_map, &fragment_varying_map,
    137         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 = vertex_shader_->signature_source();
    405   vertex_shader_->set_source("different!");
    406   TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true);
    407   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
    408       kProgramId,
    409       vertex_shader_,
    410       NULL,
    411       fragment_shader_,
    412       NULL,
    413       NULL,
    414       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    415                  base::Unretained(this))));
    416 
    417   vertex_shader_->set_source(vertex_orig_source);
    418   TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true);
    419   fragment_shader_->set_source("different!");
    420   TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
    421   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
    422       kProgramId,
    423       vertex_shader_,
    424       NULL,
    425       fragment_shader_,
    426       NULL,
    427       NULL,
    428       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    429                  base::Unretained(this))));
    430 }
    431 
    432 TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentMap) {
    433   const GLenum kFormat = 1;
    434   const int kProgramId = 10;
    435   const int kBinaryLength = 20;
    436   char test_binary[kBinaryLength];
    437   for (int i = 0; i < kBinaryLength; ++i) {
    438     test_binary[i] = i;
    439   }
    440   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
    441 
    442   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
    443   ProgramCache::LocationMap binding_map;
    444   binding_map["test"] = 512;
    445   cache_->SaveLinkedProgram(kProgramId,
    446                             vertex_shader_,
    447                             NULL,
    448                             fragment_shader_,
    449                             NULL,
    450                             &binding_map,
    451                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    452                                        base::Unretained(this)));
    453 
    454   binding_map["different!"] = 59;
    455   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
    456       kProgramId,
    457       vertex_shader_,
    458       NULL,
    459       fragment_shader_,
    460       NULL,
    461       &binding_map,
    462       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    463                  base::Unretained(this))));
    464   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
    465       kProgramId,
    466       vertex_shader_,
    467       NULL,
    468       fragment_shader_,
    469       NULL,
    470       NULL,
    471       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    472                  base::Unretained(this))));
    473 }
    474 
    475 TEST_F(MemoryProgramCacheTest, MemoryProgramCacheEviction) {
    476   const GLenum kFormat = 1;
    477   const int kProgramId = 10;
    478   const int kBinaryLength = 20;
    479   char test_binary[kBinaryLength];
    480   for (int i = 0; i < kBinaryLength; ++i) {
    481     test_binary[i] = i;
    482   }
    483   ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary);
    484 
    485 
    486   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
    487   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
    488                             fragment_shader_, NULL, NULL,
    489                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    490                                        base::Unretained(this)));
    491 
    492   const int kEvictingProgramId = 11;
    493   const GLuint kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1;
    494 
    495   // save old source and modify for new program
    496   const std::string& old_source = fragment_shader_->signature_source();
    497   fragment_shader_->set_source("al sdfkjdk");
    498   TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
    499 
    500   scoped_ptr<char[]> bigTestBinary =
    501       scoped_ptr<char[]>(new char[kEvictingBinaryLength]);
    502   for (size_t i = 0; i < kEvictingBinaryLength; ++i) {
    503     bigTestBinary[i] = i % 250;
    504   }
    505   ProgramBinaryEmulator emulator2(kEvictingBinaryLength,
    506                                   kFormat,
    507                                   bigTestBinary.get());
    508 
    509   SetExpectationsForSaveLinkedProgram(kEvictingProgramId, &emulator2);
    510   cache_->SaveLinkedProgram(kEvictingProgramId,
    511                             vertex_shader_,
    512                             NULL,
    513                             fragment_shader_,
    514                             NULL,
    515                             NULL,
    516                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    517                                        base::Unretained(this)));
    518 
    519   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
    520       vertex_shader_->signature_source(),
    521       NULL,
    522       fragment_shader_->signature_source(),
    523       NULL,
    524       NULL));
    525   EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus(
    526       old_source,
    527       NULL,
    528       fragment_shader_->signature_source(),
    529       NULL,
    530       NULL));
    531 }
    532 
    533 TEST_F(MemoryProgramCacheTest, SaveCorrectProgram) {
    534   const GLenum kFormat = 1;
    535   const int kProgramId = 10;
    536   const int kBinaryLength = 20;
    537   char test_binary[kBinaryLength];
    538   for (int i = 0; i < kBinaryLength; ++i) {
    539     test_binary[i] = i;
    540   }
    541   ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary);
    542 
    543   vertex_shader_->set_source("different!");
    544   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
    545   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
    546                             fragment_shader_, NULL, NULL,
    547                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    548                                        base::Unretained(this)));
    549 
    550   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
    551       vertex_shader_->signature_source(),
    552       NULL,
    553       fragment_shader_->signature_source(),
    554       NULL,
    555       NULL));
    556 }
    557 
    558 TEST_F(MemoryProgramCacheTest, LoadCorrectProgram) {
    559   const GLenum kFormat = 1;
    560   const int kProgramId = 10;
    561   const int kBinaryLength = 20;
    562   char test_binary[kBinaryLength];
    563   for (int i = 0; i < kBinaryLength; ++i) {
    564     test_binary[i] = i;
    565   }
    566   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
    567 
    568   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
    569   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
    570                             fragment_shader_, NULL, NULL,
    571                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    572                                        base::Unretained(this)));
    573 
    574   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
    575       vertex_shader_->signature_source(),
    576       NULL,
    577       fragment_shader_->signature_source(),
    578       NULL,
    579       NULL));
    580 
    581   SetExpectationsForLoadLinkedProgram(kProgramId, &emulator);
    582 
    583   fragment_shader_->set_source("different!");
    584   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
    585       kProgramId,
    586       vertex_shader_,
    587       NULL,
    588       fragment_shader_,
    589       NULL,
    590       NULL,
    591       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    592                  base::Unretained(this))));
    593 }
    594 
    595 TEST_F(MemoryProgramCacheTest, OverwriteOnNewSave) {
    596   const GLenum kFormat = 1;
    597   const int kProgramId = 10;
    598   const int kBinaryLength = 20;
    599   char test_binary[kBinaryLength];
    600   for (int i = 0; i < kBinaryLength; ++i) {
    601     test_binary[i] = i;
    602   }
    603   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
    604 
    605   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
    606   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
    607                             fragment_shader_, NULL, NULL,
    608                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    609                                        base::Unretained(this)));
    610 
    611 
    612   char test_binary2[kBinaryLength];
    613   for (int i = 0; i < kBinaryLength; ++i) {
    614     test_binary2[i] = (i*2) % 250;
    615   }
    616   ProgramBinaryEmulator emulator2(kBinaryLength, kFormat, test_binary2);
    617   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator2);
    618   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
    619                             fragment_shader_, NULL, NULL,
    620                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    621                                        base::Unretained(this)));
    622 
    623   SetExpectationsForLoadLinkedProgram(kProgramId, &emulator2);
    624   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
    625       kProgramId,
    626       vertex_shader_,
    627       NULL,
    628       fragment_shader_,
    629       NULL,
    630       NULL,
    631       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
    632                  base::Unretained(this))));
    633 }
    634 
    635 }  // namespace gles2
    636 }  // namespace gpu
    637