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.
5 #include "gpu/command_buffer/service/memory_program_cache.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"
18 using ::testing::ElementsAreArray
;
19 using ::testing::Invoke
;
20 using ::testing::SetArgPointee
;
21 using ::testing::SetArrayArgument
;
24 typedef gpu::gles2::ShaderTranslator::VariableMap VariableMap
;
25 } // anonymous namespace
30 class ProgramBinaryEmulator
{
32 ProgramBinaryEmulator(GLsizei length
,
39 void GetProgramBinary(GLuint program
,
48 memcpy(binary
, binary_
, length_
);
51 void ProgramBinary(GLuint program
,
55 // format and length are verified by matcher
56 EXPECT_EQ(0, memcmp(binary_
, binary
, length
));
59 GLsizei
length() const { return length_
; }
60 GLenum
format() const { return format_
; }
61 const char* binary() const { return binary_
; }
69 class MemoryProgramCacheTest
: public GpuServiceTest
{
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;
77 MemoryProgramCacheTest()
78 : cache_(new MemoryProgramCache(kCacheSizeBytes
)),
80 fragment_shader_(NULL
),
81 shader_cache_count_(0) { }
82 virtual ~MemoryProgramCacheTest() {
83 shader_manager_
.Destroy(false);
86 void ShaderCacheCb(const std::string
& key
, const std::string
& shader
) {
87 shader_cache_count_
++;
88 shader_cache_shader_
= shader
;
91 int32
shader_cache_count() { return shader_cache_count_
; }
92 const std::string
& shader_cache_shader() { return shader_cache_shader_
; }
95 virtual void SetUp() {
96 GpuServiceTest::SetUp();
98 vertex_shader_
= shader_manager_
.CreateShader(kVertexShaderClientId
,
99 kVertexShaderServiceId
,
101 fragment_shader_
= shader_manager_
.CreateShader(
102 kFragmentShaderClientId
,
103 kFragmentShaderServiceId
,
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
;
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");
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
);
133 vertex_shader_
->UpdateSource("bbbalsldkdkdkd");
134 fragment_shader_
->UpdateSource("bbbal sldkdkdkas 134 ad");
136 vertex_shader_
->SetStatus(true, NULL
, NULL
);
137 fragment_shader_
->SetStatus(true, NULL
, NULL
);
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
));
151 void SetExpectationsForLoadLinkedProgram(
152 const GLint program_id
,
153 ProgramBinaryEmulator
* emulator
) const {
154 EXPECT_CALL(*gl_
.get(),
155 ProgramBinary(program_id
,
159 .WillOnce(Invoke(emulator
, &ProgramBinaryEmulator::ProgramBinary
));
160 EXPECT_CALL(*gl_
.get(),
161 GetProgramiv(program_id
, GL_LINK_STATUS
, _
))
162 .WillOnce(SetArgPointee
<2>(GL_TRUE
));
165 void SetExpectationsForLoadLinkedProgramFailure(
166 const GLint program_id
,
167 ProgramBinaryEmulator
* emulator
) const {
168 EXPECT_CALL(*gl_
.get(),
169 ProgramBinary(program_id
,
173 .WillOnce(Invoke(emulator
, &ProgramBinaryEmulator::ProgramBinary
));
174 EXPECT_CALL(*gl_
.get(),
175 GetProgramiv(program_id
, GL_LINK_STATUS
, _
))
176 .WillOnce(SetArgPointee
<2>(GL_FALSE
));
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_
;
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
) {
195 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
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)));
203 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED
, cache_
->GetLinkedProgramStatus(
204 *vertex_shader_
->signature_source(),
206 *fragment_shader_
->signature_source(),
209 EXPECT_EQ(1, shader_cache_count());
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
) {
220 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
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)));
228 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED
, cache_
->GetLinkedProgramStatus(
229 *vertex_shader_
->signature_source(),
231 *fragment_shader_
->signature_source(),
234 EXPECT_EQ(1, shader_cache_count());
238 cache_
->LoadProgram(shader_cache_shader());
239 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED
, cache_
->GetLinkedProgramStatus(
240 *vertex_shader_
->signature_source(),
242 *fragment_shader_
->signature_source(),
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
) {
255 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
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());
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();
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());
278 SetExpectationsForLoadLinkedProgram(kProgramId
, &emulator
);
280 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS
, cache_
->LoadLinkedProgram(
287 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
288 base::Unretained(this))));
290 // apparently the hash_map implementation on android doesn't have the
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());
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
) {
310 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
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());
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();
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());
333 SetExpectationsForLoadLinkedProgram(kProgramId
, &emulator
);
336 cache_
->LoadProgram(shader_cache_shader());
338 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS
, cache_
->LoadLinkedProgram(
345 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
346 base::Unretained(this))));
348 // apparently the hash_map implementation on android doesn't have the
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());
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
) {
368 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
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)));
376 SetExpectationsForLoadLinkedProgramFailure(kProgramId
, &emulator
);
377 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE
, cache_
->LoadLinkedProgram(
384 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
385 base::Unretained(this))));
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
) {
396 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
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)));
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(
415 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
416 base::Unretained(this))));
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(
429 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
430 base::Unretained(this))));
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
) {
441 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
443 SetExpectationsForSaveLinkedProgram(kProgramId
, &emulator
);
444 ProgramCache::LocationMap binding_map
;
445 binding_map
["test"] = 512;
446 cache_
->SaveLinkedProgram(kProgramId
,
452 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
453 base::Unretained(this)));
455 binding_map
["different!"] = 59;
456 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE
, cache_
->LoadLinkedProgram(
463 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
464 base::Unretained(this))));
465 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE
, cache_
->LoadLinkedProgram(
472 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
473 base::Unretained(this))));
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
) {
484 ProgramBinaryEmulator
emulator1(kBinaryLength
, kFormat
, test_binary
);
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)));
493 const int kEvictingProgramId
= 11;
494 const GLuint kEvictingBinaryLength
= kCacheSizeBytes
- kBinaryLength
+ 1;
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
);
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;
507 ProgramBinaryEmulator
emulator2(kEvictingBinaryLength
,
509 bigTestBinary
.get());
511 SetExpectationsForSaveLinkedProgram(kEvictingProgramId
, &emulator2
);
512 cache_
->SaveLinkedProgram(kEvictingProgramId
,
518 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
519 base::Unretained(this)));
521 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED
, cache_
->GetLinkedProgramStatus(
522 *vertex_shader_
->signature_source(),
524 *fragment_shader_
->signature_source(),
527 EXPECT_EQ(ProgramCache::LINK_UNKNOWN
, cache_
->GetLinkedProgramStatus(
530 *fragment_shader_
->signature_source(),
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
) {
543 ProgramBinaryEmulator
emulator1(kBinaryLength
, kFormat
, test_binary
);
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)));
552 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED
, cache_
->GetLinkedProgramStatus(
553 *vertex_shader_
->signature_source(),
555 *fragment_shader_
->signature_source(),
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
) {
568 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
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)));
576 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED
, cache_
->GetLinkedProgramStatus(
577 *vertex_shader_
->signature_source(),
579 *fragment_shader_
->signature_source(),
583 SetExpectationsForLoadLinkedProgram(kProgramId
, &emulator
);
585 fragment_shader_
->UpdateSource("different!");
586 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS
, cache_
->LoadLinkedProgram(
593 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
594 base::Unretained(this))));
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
) {
605 ProgramBinaryEmulator
emulator(kBinaryLength
, kFormat
, test_binary
);
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)));
614 char test_binary2
[kBinaryLength
];
615 for (int i
= 0; i
< kBinaryLength
; ++i
) {
616 test_binary2
[i
] = (i
*2) % 250;
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)));
625 SetExpectationsForLoadLinkedProgram(kProgramId
, &emulator2
);
626 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS
, cache_
->LoadLinkedProgram(
633 base::Bind(&MemoryProgramCacheTest::ShaderCacheCb
,
634 base::Unretained(this))));