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