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/program_manager.h"
6
7#include <algorithm>
8
9#include "base/memory/scoped_ptr.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_util.h"
12#include "gpu/command_buffer/common/gles2_cmd_format.h"
13#include "gpu/command_buffer/common/gles2_cmd_utils.h"
14#include "gpu/command_buffer/service/common_decoder.h"
15#include "gpu/command_buffer/service/feature_info.h"
16#include "gpu/command_buffer/service/gpu_service_test.h"
17#include "gpu/command_buffer/service/mocks.h"
18#include "gpu/command_buffer/service/shader_manager.h"
19#include "gpu/command_buffer/service/test_helper.h"
20#include "testing/gtest/include/gtest/gtest.h"
21#include "ui/gl/gl_mock.h"
22
23using ::testing::_;
24using ::testing::DoAll;
25using ::testing::InSequence;
26using ::testing::MatcherCast;
27using ::testing::Pointee;
28using ::testing::Return;
29using ::testing::ReturnRef;
30using ::testing::SetArrayArgument;
31using ::testing::SetArgumentPointee;
32using ::testing::StrEq;
33
34namespace gpu {
35namespace gles2 {
36
37namespace {
38const uint32 kMaxVaryingVectors = 8;
39
40void ShaderCacheCb(const std::string& key, const std::string& shader) {}
41}  // namespace anonymous
42
43class ProgramManagerTest : public GpuServiceTest {
44 public:
45  ProgramManagerTest() : manager_(NULL, kMaxVaryingVectors) { }
46  virtual ~ProgramManagerTest() {
47    manager_.Destroy(false);
48  }
49
50 protected:
51  ProgramManager manager_;
52};
53
54TEST_F(ProgramManagerTest, Basic) {
55  const GLuint kClient1Id = 1;
56  const GLuint kService1Id = 11;
57  const GLuint kClient2Id = 2;
58  // Check we can create program.
59  manager_.CreateProgram(kClient1Id, kService1Id);
60  // Check program got created.
61  Program* program1 = manager_.GetProgram(kClient1Id);
62  ASSERT_TRUE(program1 != NULL);
63  GLuint client_id = 0;
64  EXPECT_TRUE(manager_.GetClientId(program1->service_id(), &client_id));
65  EXPECT_EQ(kClient1Id, client_id);
66  // Check we get nothing for a non-existent program.
67  EXPECT_TRUE(manager_.GetProgram(kClient2Id) == NULL);
68}
69
70TEST_F(ProgramManagerTest, Destroy) {
71  const GLuint kClient1Id = 1;
72  const GLuint kService1Id = 11;
73  // Check we can create program.
74  Program* program0 = manager_.CreateProgram(kClient1Id, kService1Id);
75  ASSERT_TRUE(program0 != NULL);
76  // Check program got created.
77  Program* program1 = manager_.GetProgram(kClient1Id);
78  ASSERT_EQ(program0, program1);
79  EXPECT_CALL(*gl_, DeleteProgram(kService1Id))
80      .Times(1)
81      .RetiresOnSaturation();
82  manager_.Destroy(true);
83  // Check the resources were released.
84  program1 = manager_.GetProgram(kClient1Id);
85  ASSERT_TRUE(program1 == NULL);
86}
87
88TEST_F(ProgramManagerTest, DeleteBug) {
89  ShaderManager shader_manager;
90  const GLuint kClient1Id = 1;
91  const GLuint kClient2Id = 2;
92  const GLuint kService1Id = 11;
93  const GLuint kService2Id = 12;
94  // Check we can create program.
95  scoped_refptr<Program> program1(
96      manager_.CreateProgram(kClient1Id, kService1Id));
97  scoped_refptr<Program> program2(
98      manager_.CreateProgram(kClient2Id, kService2Id));
99  // Check program got created.
100  ASSERT_TRUE(program1.get());
101  ASSERT_TRUE(program2.get());
102  manager_.UseProgram(program1.get());
103  manager_.MarkAsDeleted(&shader_manager, program1.get());
104  //  Program will be deleted when last ref is released.
105  EXPECT_CALL(*gl_, DeleteProgram(kService2Id))
106      .Times(1)
107      .RetiresOnSaturation();
108  manager_.MarkAsDeleted(&shader_manager, program2.get());
109  EXPECT_TRUE(manager_.IsOwned(program1.get()));
110  EXPECT_FALSE(manager_.IsOwned(program2.get()));
111}
112
113TEST_F(ProgramManagerTest, Program) {
114  const GLuint kClient1Id = 1;
115  const GLuint kService1Id = 11;
116  // Check we can create program.
117  Program* program1 = manager_.CreateProgram(
118      kClient1Id, kService1Id);
119  ASSERT_TRUE(program1);
120  EXPECT_EQ(kService1Id, program1->service_id());
121  EXPECT_FALSE(program1->InUse());
122  EXPECT_FALSE(program1->IsValid());
123  EXPECT_FALSE(program1->IsDeleted());
124  EXPECT_FALSE(program1->CanLink());
125  EXPECT_TRUE(program1->log_info() == NULL);
126}
127
128class ProgramManagerWithShaderTest : public GpuServiceTest {
129 public:
130  ProgramManagerWithShaderTest()
131      :  manager_(NULL, kMaxVaryingVectors), program_(NULL) {
132  }
133
134  virtual ~ProgramManagerWithShaderTest() {
135    manager_.Destroy(false);
136    shader_manager_.Destroy(false);
137  }
138
139  static const GLint kNumVertexAttribs = 16;
140
141  static const GLuint kClientProgramId = 123;
142  static const GLuint kServiceProgramId = 456;
143  static const GLuint kVertexShaderClientId = 201;
144  static const GLuint kFragmentShaderClientId = 202;
145  static const GLuint kVertexShaderServiceId = 301;
146  static const GLuint kFragmentShaderServiceId = 302;
147
148  static const char* kAttrib1Name;
149  static const char* kAttrib2Name;
150  static const char* kAttrib3Name;
151  static const GLint kAttrib1Size = 1;
152  static const GLint kAttrib2Size = 1;
153  static const GLint kAttrib3Size = 1;
154  static const int kAttrib1Precision = SH_PRECISION_MEDIUMP;
155  static const int kAttrib2Precision = SH_PRECISION_HIGHP;
156  static const int kAttrib3Precision = SH_PRECISION_LOWP;
157  static const int kAttribStaticUse = 0;
158  static const GLint kAttrib1Location = 0;
159  static const GLint kAttrib2Location = 1;
160  static const GLint kAttrib3Location = 2;
161  static const GLenum kAttrib1Type = GL_FLOAT_VEC4;
162  static const GLenum kAttrib2Type = GL_FLOAT_VEC2;
163  static const GLenum kAttrib3Type = GL_FLOAT_VEC3;
164  static const GLint kInvalidAttribLocation = 30;
165  static const GLint kBadAttribIndex = kNumVertexAttribs;
166
167  static const char* kUniform1Name;
168  static const char* kUniform2Name;
169  static const char* kUniform3BadName;
170  static const char* kUniform3GoodName;
171  static const GLint kUniform1Size = 1;
172  static const GLint kUniform2Size = 3;
173  static const GLint kUniform3Size = 2;
174  static const int kUniform1Precision = SH_PRECISION_LOWP;
175  static const int kUniform2Precision = SH_PRECISION_MEDIUMP;
176  static const int kUniform3Precision = SH_PRECISION_HIGHP;
177  static const int kUniform1StaticUse = 1;
178  static const int kUniform2StaticUse = 1;
179  static const int kUniform3StaticUse = 1;
180  static const GLint kUniform1FakeLocation = 0;  // These are hard coded
181  static const GLint kUniform2FakeLocation = 1;  // to match
182  static const GLint kUniform3FakeLocation = 2;  // ProgramManager.
183  static const GLint kUniform1RealLocation = 11;
184  static const GLint kUniform2RealLocation = 22;
185  static const GLint kUniform3RealLocation = 33;
186  static const GLint kUniform1DesiredLocation = -1;
187  static const GLint kUniform2DesiredLocation = -1;
188  static const GLint kUniform3DesiredLocation = -1;
189  static const GLenum kUniform1Type = GL_FLOAT_VEC4;
190  static const GLenum kUniform2Type = GL_INT_VEC2;
191  static const GLenum kUniform3Type = GL_FLOAT_VEC3;
192  static const GLint kInvalidUniformLocation = 30;
193  static const GLint kBadUniformIndex = 1000;
194
195  static const size_t kNumAttribs;
196  static const size_t kNumUniforms;
197
198 protected:
199  typedef TestHelper::AttribInfo AttribInfo;
200  typedef TestHelper::UniformInfo UniformInfo;
201
202  typedef enum {
203    kVarUniform,
204    kVarVarying,
205    kVarAttribute
206  } VarCategory;
207
208  typedef struct {
209    int type;
210    int size;
211    int precision;
212    int static_use;
213    std::string name;
214    VarCategory category;
215  } VarInfo;
216
217  virtual void SetUp() {
218    GpuServiceTest::SetUp();
219
220    SetupDefaultShaderExpectations();
221
222    Shader* vertex_shader = shader_manager_.CreateShader(
223        kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
224    Shader* fragment_shader =
225        shader_manager_.CreateShader(
226            kFragmentShaderClientId, kFragmentShaderServiceId,
227            GL_FRAGMENT_SHADER);
228    ASSERT_TRUE(vertex_shader != NULL);
229    ASSERT_TRUE(fragment_shader != NULL);
230    TestHelper::SetShaderStates(gl_.get(), vertex_shader, true);
231    TestHelper::SetShaderStates(gl_.get(), fragment_shader, true);
232
233    program_ = manager_.CreateProgram(
234        kClientProgramId, kServiceProgramId);
235    ASSERT_TRUE(program_ != NULL);
236
237    program_->AttachShader(&shader_manager_, vertex_shader);
238    program_->AttachShader(&shader_manager_, fragment_shader);
239    program_->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
240                   base::Bind(&ShaderCacheCb));
241  }
242
243  void SetupShader(AttribInfo* attribs, size_t num_attribs,
244                   UniformInfo* uniforms, size_t num_uniforms,
245                   GLuint service_id) {
246    TestHelper::SetupShader(
247        gl_.get(), attribs, num_attribs, uniforms, num_uniforms, service_id);
248  }
249
250  void SetupDefaultShaderExpectations() {
251    SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
252                kServiceProgramId);
253  }
254
255  void SetupExpectationsForClearingUniforms(
256      UniformInfo* uniforms, size_t num_uniforms) {
257    TestHelper::SetupExpectationsForClearingUniforms(
258        gl_.get(), uniforms, num_uniforms);
259  }
260
261  // Return true if link status matches expected_link_status
262  bool LinkAsExpected(Program* program,
263                      bool expected_link_status) {
264    GLuint service_id = program->service_id();
265    if (expected_link_status) {
266      SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
267                  service_id);
268    }
269    program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
270                  base::Bind(&ShaderCacheCb));
271    GLint link_status;
272    program->GetProgramiv(GL_LINK_STATUS, &link_status);
273    return (static_cast<bool>(link_status) == expected_link_status);
274  }
275
276  Program* SetupShaderVariableTest(const VarInfo* vertex_variables,
277                                   size_t vertex_variable_size,
278                                   const VarInfo* fragment_variables,
279                                   size_t fragment_variable_size) {
280    // Set up shader
281    const GLuint kVShaderClientId = 1;
282    const GLuint kVShaderServiceId = 11;
283    const GLuint kFShaderClientId = 2;
284    const GLuint kFShaderServiceId = 12;
285
286    ShaderTranslator::VariableMap vertex_attrib_map;
287    ShaderTranslator::VariableMap vertex_uniform_map;
288    ShaderTranslator::VariableMap vertex_varying_map;
289    for (size_t ii = 0; ii < vertex_variable_size; ++ii) {
290      ShaderTranslator::VariableMap* map = NULL;
291      switch (vertex_variables[ii].category) {
292        case kVarAttribute:
293          map = &vertex_attrib_map;
294          break;
295        case kVarUniform:
296          map = &vertex_uniform_map;
297          break;
298        case kVarVarying:
299          map = &vertex_varying_map;
300          break;
301        default:
302          NOTREACHED();
303      }
304      (*map)[vertex_variables[ii].name] =
305          ShaderTranslator::VariableInfo(vertex_variables[ii].type,
306                                         vertex_variables[ii].size,
307                                         vertex_variables[ii].precision,
308                                         vertex_variables[ii].static_use,
309                                         vertex_variables[ii].name);
310    }
311
312    ShaderTranslator::VariableMap frag_attrib_map;
313    ShaderTranslator::VariableMap frag_uniform_map;
314    ShaderTranslator::VariableMap frag_varying_map;
315    for (size_t ii = 0; ii < fragment_variable_size; ++ii) {
316      ShaderTranslator::VariableMap* map = NULL;
317      switch (fragment_variables[ii].category) {
318        case kVarAttribute:
319          map = &frag_attrib_map;
320          break;
321        case kVarUniform:
322          map = &frag_uniform_map;
323          break;
324        case kVarVarying:
325          map = &frag_varying_map;
326          break;
327        default:
328          NOTREACHED();
329      }
330      (*map)[fragment_variables[ii].name] =
331          ShaderTranslator::VariableInfo(fragment_variables[ii].type,
332                                         fragment_variables[ii].size,
333                                         fragment_variables[ii].precision,
334                                         fragment_variables[ii].static_use,
335                                         fragment_variables[ii].name);
336    }
337
338    // Check we can create shader.
339    Shader* vshader = shader_manager_.CreateShader(
340        kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
341    Shader* fshader = shader_manager_.CreateShader(
342        kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
343    // Check shader got created.
344    EXPECT_TRUE(vshader != NULL && fshader != NULL);
345    // Set Status
346    TestHelper::SetShaderStates(
347        gl_.get(), vshader, true, NULL, NULL,
348        &vertex_attrib_map, &vertex_uniform_map, &vertex_varying_map, NULL);
349    TestHelper::SetShaderStates(
350        gl_.get(), fshader, true, NULL, NULL,
351        &frag_attrib_map, &frag_uniform_map, &frag_varying_map, NULL);
352
353    // Set up program
354    const GLuint kClientProgramId = 6666;
355    const GLuint kServiceProgramId = 8888;
356    Program* program =
357        manager_.CreateProgram(kClientProgramId, kServiceProgramId);
358    EXPECT_TRUE(program != NULL);
359    EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
360    EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
361    return program;
362  }
363
364  static AttribInfo kAttribs[];
365  static UniformInfo kUniforms[];
366
367  ProgramManager manager_;
368  Program* program_;
369  ShaderManager shader_manager_;
370};
371
372ProgramManagerWithShaderTest::AttribInfo
373    ProgramManagerWithShaderTest::kAttribs[] = {
374  { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
375  { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, },
376  { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
377};
378
379// GCC requires these declarations, but MSVC requires they not be present
380#ifndef COMPILER_MSVC
381const GLint ProgramManagerWithShaderTest::kNumVertexAttribs;
382const GLuint ProgramManagerWithShaderTest::kClientProgramId;
383const GLuint ProgramManagerWithShaderTest::kServiceProgramId;
384const GLuint ProgramManagerWithShaderTest::kVertexShaderClientId;
385const GLuint ProgramManagerWithShaderTest::kFragmentShaderClientId;
386const GLuint ProgramManagerWithShaderTest::kVertexShaderServiceId;
387const GLuint ProgramManagerWithShaderTest::kFragmentShaderServiceId;
388const GLint ProgramManagerWithShaderTest::kAttrib1Size;
389const GLint ProgramManagerWithShaderTest::kAttrib2Size;
390const GLint ProgramManagerWithShaderTest::kAttrib3Size;
391const GLint ProgramManagerWithShaderTest::kAttrib1Location;
392const GLint ProgramManagerWithShaderTest::kAttrib2Location;
393const GLint ProgramManagerWithShaderTest::kAttrib3Location;
394const GLenum ProgramManagerWithShaderTest::kAttrib1Type;
395const GLenum ProgramManagerWithShaderTest::kAttrib2Type;
396const GLenum ProgramManagerWithShaderTest::kAttrib3Type;
397const GLint ProgramManagerWithShaderTest::kInvalidAttribLocation;
398const GLint ProgramManagerWithShaderTest::kBadAttribIndex;
399const GLint ProgramManagerWithShaderTest::kUniform1Size;
400const GLint ProgramManagerWithShaderTest::kUniform2Size;
401const GLint ProgramManagerWithShaderTest::kUniform3Size;
402const GLint ProgramManagerWithShaderTest::kUniform1FakeLocation;
403const GLint ProgramManagerWithShaderTest::kUniform2FakeLocation;
404const GLint ProgramManagerWithShaderTest::kUniform3FakeLocation;
405const GLint ProgramManagerWithShaderTest::kUniform1RealLocation;
406const GLint ProgramManagerWithShaderTest::kUniform2RealLocation;
407const GLint ProgramManagerWithShaderTest::kUniform3RealLocation;
408const GLint ProgramManagerWithShaderTest::kUniform1DesiredLocation;
409const GLint ProgramManagerWithShaderTest::kUniform2DesiredLocation;
410const GLint ProgramManagerWithShaderTest::kUniform3DesiredLocation;
411const GLenum ProgramManagerWithShaderTest::kUniform1Type;
412const GLenum ProgramManagerWithShaderTest::kUniform2Type;
413const GLenum ProgramManagerWithShaderTest::kUniform3Type;
414const GLint ProgramManagerWithShaderTest::kInvalidUniformLocation;
415const GLint ProgramManagerWithShaderTest::kBadUniformIndex;
416#endif
417
418const size_t ProgramManagerWithShaderTest::kNumAttribs =
419    arraysize(ProgramManagerWithShaderTest::kAttribs);
420
421ProgramManagerWithShaderTest::UniformInfo
422    ProgramManagerWithShaderTest::kUniforms[] = {
423  { kUniform1Name,
424    kUniform1Size,
425    kUniform1Type,
426    kUniform1FakeLocation,
427    kUniform1RealLocation,
428    kUniform1DesiredLocation,
429    kUniform1Name,
430  },
431  { kUniform2Name,
432    kUniform2Size,
433    kUniform2Type,
434    kUniform2FakeLocation,
435    kUniform2RealLocation,
436    kUniform2DesiredLocation,
437    kUniform2Name,
438  },
439  { kUniform3BadName,
440    kUniform3Size,
441    kUniform3Type,
442    kUniform3FakeLocation,
443    kUniform3RealLocation,
444    kUniform3DesiredLocation,
445    kUniform3GoodName,
446  },
447};
448
449const size_t ProgramManagerWithShaderTest::kNumUniforms =
450    arraysize(ProgramManagerWithShaderTest::kUniforms);
451
452const char* ProgramManagerWithShaderTest::kAttrib1Name = "attrib1";
453const char* ProgramManagerWithShaderTest::kAttrib2Name = "attrib2";
454const char* ProgramManagerWithShaderTest::kAttrib3Name = "attrib3";
455const char* ProgramManagerWithShaderTest::kUniform1Name = "uniform1";
456// Correctly has array spec.
457const char* ProgramManagerWithShaderTest::kUniform2Name = "uniform2[0]";
458// Incorrectly missing array spec.
459const char* ProgramManagerWithShaderTest::kUniform3BadName = "uniform3";
460const char* ProgramManagerWithShaderTest::kUniform3GoodName = "uniform3[0]";
461
462TEST_F(ProgramManagerWithShaderTest, GetAttribInfos) {
463  const Program* program = manager_.GetProgram(kClientProgramId);
464  ASSERT_TRUE(program != NULL);
465  const Program::AttribInfoVector& infos =
466      program->GetAttribInfos();
467  ASSERT_EQ(kNumAttribs, infos.size());
468  for (size_t ii = 0; ii < kNumAttribs; ++ii) {
469    const Program::VertexAttrib& info = infos[ii];
470    const AttribInfo& expected = kAttribs[ii];
471    EXPECT_EQ(expected.size, info.size);
472    EXPECT_EQ(expected.type, info.type);
473    EXPECT_EQ(expected.location, info.location);
474    EXPECT_STREQ(expected.name, info.name.c_str());
475  }
476}
477
478TEST_F(ProgramManagerWithShaderTest, GetAttribInfo) {
479  const GLint kValidIndex = 1;
480  const GLint kInvalidIndex = 1000;
481  const Program* program = manager_.GetProgram(kClientProgramId);
482  ASSERT_TRUE(program != NULL);
483  const Program::VertexAttrib* info =
484      program->GetAttribInfo(kValidIndex);
485  ASSERT_TRUE(info != NULL);
486  EXPECT_EQ(kAttrib2Size, info->size);
487  EXPECT_EQ(kAttrib2Type, info->type);
488  EXPECT_EQ(kAttrib2Location, info->location);
489  EXPECT_STREQ(kAttrib2Name, info->name.c_str());
490  EXPECT_TRUE(program->GetAttribInfo(kInvalidIndex) == NULL);
491}
492
493TEST_F(ProgramManagerWithShaderTest, GetAttribLocation) {
494  const char* kInvalidName = "foo";
495  const Program* program = manager_.GetProgram(kClientProgramId);
496  ASSERT_TRUE(program != NULL);
497  EXPECT_EQ(kAttrib2Location, program->GetAttribLocation(kAttrib2Name));
498  EXPECT_EQ(-1, program->GetAttribLocation(kInvalidName));
499}
500
501TEST_F(ProgramManagerWithShaderTest, GetUniformInfo) {
502  const GLint kInvalidIndex = 1000;
503  const Program* program = manager_.GetProgram(kClientProgramId);
504  ASSERT_TRUE(program != NULL);
505  const Program::UniformInfo* info =
506      program->GetUniformInfo(0);
507  ASSERT_TRUE(info != NULL);
508  EXPECT_EQ(kUniform1Size, info->size);
509  EXPECT_EQ(kUniform1Type, info->type);
510  EXPECT_EQ(kUniform1RealLocation, info->element_locations[0]);
511  EXPECT_STREQ(kUniform1Name, info->name.c_str());
512  info = program->GetUniformInfo(1);
513  ASSERT_TRUE(info != NULL);
514  EXPECT_EQ(kUniform2Size, info->size);
515  EXPECT_EQ(kUniform2Type, info->type);
516  EXPECT_EQ(kUniform2RealLocation, info->element_locations[0]);
517  EXPECT_STREQ(kUniform2Name, info->name.c_str());
518  info = program->GetUniformInfo(2);
519  // We emulate certain OpenGL drivers by supplying the name without
520  // the array spec. Our implementation should correctly add the required spec.
521  ASSERT_TRUE(info != NULL);
522  EXPECT_EQ(kUniform3Size, info->size);
523  EXPECT_EQ(kUniform3Type, info->type);
524  EXPECT_EQ(kUniform3RealLocation, info->element_locations[0]);
525  EXPECT_STREQ(kUniform3GoodName, info->name.c_str());
526  EXPECT_TRUE(program->GetUniformInfo(kInvalidIndex) == NULL);
527}
528
529TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) {
530  static const GLuint kClientProgramId = 124;
531  static const GLuint kServiceProgramId = 457;
532  Program* program = manager_.CreateProgram(
533      kClientProgramId, kServiceProgramId);
534  ASSERT_TRUE(program != NULL);
535  EXPECT_FALSE(program->CanLink());
536  const GLuint kVShaderClientId = 2001;
537  const GLuint kFShaderClientId = 2002;
538  const GLuint kVShaderServiceId = 3001;
539  const GLuint kFShaderServiceId = 3002;
540  Shader* vshader = shader_manager_.CreateShader(
541      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
542  ASSERT_TRUE(vshader != NULL);
543  TestHelper::SetShaderStates(gl_.get(), vshader, true);
544  Shader* fshader = shader_manager_.CreateShader(
545      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
546  ASSERT_TRUE(fshader != NULL);
547  TestHelper::SetShaderStates(gl_.get(), fshader, true);
548  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
549  EXPECT_FALSE(program->CanLink());
550  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
551  EXPECT_TRUE(program->CanLink());
552  program->DetachShader(&shader_manager_, vshader);
553  EXPECT_FALSE(program->CanLink());
554  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
555  EXPECT_TRUE(program->CanLink());
556  program->DetachShader(&shader_manager_, fshader);
557  EXPECT_FALSE(program->CanLink());
558  EXPECT_FALSE(program->AttachShader(&shader_manager_, vshader));
559  EXPECT_FALSE(program->CanLink());
560  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
561  EXPECT_TRUE(program->CanLink());
562  TestHelper::SetShaderStates(gl_.get(), vshader, false);
563  EXPECT_FALSE(program->CanLink());
564  TestHelper::SetShaderStates(gl_.get(), vshader, true);
565  EXPECT_TRUE(program->CanLink());
566  TestHelper::SetShaderStates(gl_.get(), fshader, false);
567  EXPECT_FALSE(program->CanLink());
568  TestHelper::SetShaderStates(gl_.get(), fshader, true);
569  EXPECT_TRUE(program->CanLink());
570  EXPECT_TRUE(program->DetachShader(&shader_manager_, fshader));
571  EXPECT_FALSE(program->DetachShader(&shader_manager_, fshader));
572}
573
574TEST_F(ProgramManagerWithShaderTest, GetUniformFakeLocation) {
575  const Program* program = manager_.GetProgram(kClientProgramId);
576  ASSERT_TRUE(program != NULL);
577  // Emulate the situation that uniform3[1] isn't used and optimized out by
578  // a driver, so it's location is -1.
579  Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>(
580      program->GetUniformInfo(2));
581  ASSERT_TRUE(uniform != NULL && kUniform3Size == 2);
582  EXPECT_EQ(kUniform3Size, uniform->size);
583  uniform->element_locations[1] = -1;
584  EXPECT_EQ(kUniform1FakeLocation,
585            program->GetUniformFakeLocation(kUniform1Name));
586  EXPECT_EQ(kUniform2FakeLocation,
587            program->GetUniformFakeLocation(kUniform2Name));
588  EXPECT_EQ(kUniform3FakeLocation,
589            program->GetUniformFakeLocation(kUniform3BadName));
590  // Check we can get uniform2 as "uniform2" even though the name is
591  // "uniform2[0]"
592  EXPECT_EQ(kUniform2FakeLocation,
593            program->GetUniformFakeLocation("uniform2"));
594  // Check we can get uniform3 as "uniform3[0]" even though we simulated GL
595  // returning "uniform3"
596  EXPECT_EQ(kUniform3FakeLocation,
597            program->GetUniformFakeLocation(kUniform3GoodName));
598  // Check that we can get the locations of the array elements > 1
599  EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation, 1),
600            program->GetUniformFakeLocation("uniform2[1]"));
601  EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation, 2),
602            program->GetUniformFakeLocation("uniform2[2]"));
603  EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform2[3]"));
604  EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform3[1]"));
605  EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform3[2]"));
606}
607
608TEST_F(ProgramManagerWithShaderTest, GetUniformInfoByFakeLocation) {
609  const GLint kInvalidLocation = 1234;
610  const Program::UniformInfo* info;
611  const Program* program = manager_.GetProgram(kClientProgramId);
612  GLint real_location = -1;
613  GLint array_index = -1;
614  ASSERT_TRUE(program != NULL);
615  info = program->GetUniformInfoByFakeLocation(
616      kUniform2FakeLocation, &real_location, &array_index);
617  EXPECT_EQ(kUniform2RealLocation, real_location);
618  EXPECT_EQ(0, array_index);
619  ASSERT_TRUE(info != NULL);
620  EXPECT_EQ(kUniform2Type, info->type);
621  real_location = -1;
622  array_index = -1;
623  info = program->GetUniformInfoByFakeLocation(
624      kInvalidLocation, &real_location, &array_index);
625  EXPECT_TRUE(info == NULL);
626  EXPECT_EQ(-1, real_location);
627  EXPECT_EQ(-1, array_index);
628  GLint loc = program->GetUniformFakeLocation("uniform2[2]");
629  info = program->GetUniformInfoByFakeLocation(
630      loc, &real_location, &array_index);
631  ASSERT_TRUE(info != NULL);
632  EXPECT_EQ(kUniform2RealLocation + 2 * 2, real_location);
633  EXPECT_EQ(2, array_index);
634}
635
636// Some GL drivers incorrectly return gl_DepthRange and possibly other uniforms
637// that start with "gl_". Our implementation catches these and does not allow
638// them back to client.
639TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) {
640  static const char* kUniform2Name = "gl_longNameWeCanCheckFor";
641  static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
642    { kUniform1Name,
643      kUniform1Size,
644      kUniform1Type,
645      kUniform1FakeLocation,
646      kUniform1RealLocation,
647      kUniform1DesiredLocation,
648      kUniform1Name,
649    },
650    { kUniform2Name,
651      kUniform2Size,
652      kUniform2Type,
653      kUniform2FakeLocation,
654      kUniform2RealLocation,
655      kUniform2DesiredLocation,
656      kUniform2Name,
657    },
658    { kUniform3BadName,
659      kUniform3Size,
660      kUniform3Type,
661      kUniform3FakeLocation,
662      kUniform3RealLocation,
663      kUniform3DesiredLocation,
664      kUniform3GoodName,
665    },
666  };
667  const size_t kNumUniforms = arraysize(kUniforms);
668  static const GLuint kClientProgramId = 1234;
669  static const GLuint kServiceProgramId = 5679;
670  const GLuint kVShaderClientId = 2001;
671  const GLuint kFShaderClientId = 2002;
672  const GLuint kVShaderServiceId = 3001;
673  const GLuint kFShaderServiceId = 3002;
674  SetupShader(
675      kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId);
676  Shader* vshader = shader_manager_.CreateShader(
677      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
678  ASSERT_TRUE(vshader != NULL);
679  TestHelper::SetShaderStates(gl_.get(), vshader, true);
680  Shader* fshader = shader_manager_.CreateShader(
681      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
682  ASSERT_TRUE(fshader != NULL);
683  TestHelper::SetShaderStates(gl_.get(), fshader, true);
684  Program* program =
685      manager_.CreateProgram(kClientProgramId, kServiceProgramId);
686  ASSERT_TRUE(program != NULL);
687  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
688  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
689  program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
690                base::Bind(&ShaderCacheCb));
691  GLint value = 0;
692  program->GetProgramiv(GL_ACTIVE_ATTRIBUTES, &value);
693  EXPECT_EQ(3, value);
694  // Check that we skipped the "gl_" uniform.
695  program->GetProgramiv(GL_ACTIVE_UNIFORMS, &value);
696  EXPECT_EQ(2, value);
697  // Check that our max length adds room for the array spec and is not as long
698  // as the "gl_" uniform we skipped.
699  // +4u is to account for "gl_" and NULL terminator.
700  program->GetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH, &value);
701  EXPECT_EQ(strlen(kUniform3BadName) + 4u, static_cast<size_t>(value));
702}
703
704// Test the bug comparing similar array names is fixed.
705TEST_F(ProgramManagerWithShaderTest, SimilarArrayNames) {
706  static const char* kUniform2Name = "u_nameLong[0]";
707  static const char* kUniform3Name = "u_name[0]";
708  static const GLint kUniform2Size = 2;
709  static const GLint kUniform3Size = 2;
710  static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
711    { kUniform1Name,
712      kUniform1Size,
713      kUniform1Type,
714      kUniform1FakeLocation,
715      kUniform1RealLocation,
716      kUniform1DesiredLocation,
717      kUniform1Name,
718    },
719    { kUniform2Name,
720      kUniform2Size,
721      kUniform2Type,
722      kUniform2FakeLocation,
723      kUniform2RealLocation,
724      kUniform2DesiredLocation,
725      kUniform2Name,
726    },
727    { kUniform3Name,
728      kUniform3Size,
729      kUniform3Type,
730      kUniform3FakeLocation,
731      kUniform3RealLocation,
732      kUniform3DesiredLocation,
733      kUniform3Name,
734    },
735  };
736  const size_t kNumUniforms = arraysize(kUniforms);
737  static const GLuint kClientProgramId = 1234;
738  static const GLuint kServiceProgramId = 5679;
739  const GLuint kVShaderClientId = 2001;
740  const GLuint kFShaderClientId = 2002;
741  const GLuint kVShaderServiceId = 3001;
742  const GLuint kFShaderServiceId = 3002;
743  SetupShader(
744      kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId);
745  Shader* vshader = shader_manager_.CreateShader(
746      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
747  ASSERT_TRUE(vshader != NULL);
748  TestHelper::SetShaderStates(gl_.get(), vshader, true);
749  Shader* fshader = shader_manager_.CreateShader(
750      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
751  ASSERT_TRUE(fshader != NULL);
752  TestHelper::SetShaderStates(gl_.get(), fshader, true);
753  Program* program =
754      manager_.CreateProgram(kClientProgramId, kServiceProgramId);
755  ASSERT_TRUE(program != NULL);
756  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
757  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
758  program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
759                base::Bind(&ShaderCacheCb));
760
761  // Check that we get the correct locations.
762  EXPECT_EQ(kUniform2FakeLocation,
763            program->GetUniformFakeLocation(kUniform2Name));
764  EXPECT_EQ(kUniform3FakeLocation,
765            program->GetUniformFakeLocation(kUniform3Name));
766}
767
768// Some GL drivers incorrectly return the wrong type. For example they return
769// GL_FLOAT_VEC2 when they should return GL_FLOAT_MAT2. Check we handle this.
770TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) {
771  static GLenum kAttrib2BadType = GL_FLOAT_VEC2;
772  static GLenum kAttrib2GoodType = GL_FLOAT_MAT2;
773  static GLenum kUniform2BadType = GL_FLOAT_VEC3;
774  static GLenum kUniform2GoodType = GL_FLOAT_MAT3;
775  ShaderTranslator::VariableMap attrib_map;
776  ShaderTranslator::VariableMap uniform_map;
777  ShaderTranslator::VariableMap varying_map;
778  attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo(
779      kAttrib1Type, kAttrib1Size, kAttrib1Precision,
780      kAttribStaticUse, kAttrib1Name);
781  attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo(
782      kAttrib2GoodType, kAttrib2Size, kAttrib2Precision,
783      kAttribStaticUse, kAttrib2Name);
784  attrib_map[kAttrib3Name] = ShaderTranslatorInterface::VariableInfo(
785      kAttrib3Type, kAttrib3Size, kAttrib3Precision,
786      kAttribStaticUse, kAttrib3Name);
787  uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo(
788      kUniform1Type, kUniform1Size, kUniform1Precision,
789      kUniform1StaticUse, kUniform1Name);
790  uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo(
791      kUniform2GoodType, kUniform2Size, kUniform2Precision,
792      kUniform2StaticUse, kUniform2Name);
793  uniform_map[kUniform3GoodName] = ShaderTranslatorInterface::VariableInfo(
794      kUniform3Type, kUniform3Size, kUniform3Precision,
795      kUniform3StaticUse, kUniform3GoodName);
796  const GLuint kVShaderClientId = 2001;
797  const GLuint kFShaderClientId = 2002;
798  const GLuint kVShaderServiceId = 3001;
799  const GLuint kFShaderServiceId = 3002;
800  Shader* vshader = shader_manager_.CreateShader(
801      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
802  ASSERT_TRUE(vshader != NULL);
803  TestHelper::SetShaderStates(
804      gl_.get(), vshader, true, NULL, NULL,
805      &attrib_map, &uniform_map, &varying_map, NULL);
806  Shader* fshader = shader_manager_.CreateShader(
807      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
808  ASSERT_TRUE(fshader != NULL);
809  TestHelper::SetShaderStates(
810      gl_.get(), fshader, true, NULL, NULL,
811      &attrib_map, &uniform_map, &varying_map, NULL);
812  static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = {
813    { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
814    { kAttrib2Name, kAttrib2Size, kAttrib2BadType, kAttrib2Location, },
815    { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
816  };
817  static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
818    { kUniform1Name,
819      kUniform1Size,
820      kUniform1Type,
821      kUniform1FakeLocation,
822      kUniform1RealLocation,
823      kUniform1DesiredLocation,
824      kUniform1Name,
825    },
826    { kUniform2Name,
827      kUniform2Size,
828      kUniform2BadType,
829      kUniform2FakeLocation,
830      kUniform2RealLocation,
831      kUniform2DesiredLocation,
832      kUniform2Name,
833    },
834    { kUniform3BadName,
835      kUniform3Size,
836      kUniform3Type,
837      kUniform3FakeLocation,
838      kUniform3RealLocation,
839      kUniform3DesiredLocation,
840      kUniform3GoodName,
841    },
842  };
843  const size_t kNumAttribs= arraysize(kAttribs);
844  const size_t kNumUniforms = arraysize(kUniforms);
845  static const GLuint kClientProgramId = 1234;
846  static const GLuint kServiceProgramId = 5679;
847  SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
848              kServiceProgramId);
849  Program* program = manager_.CreateProgram(
850      kClientProgramId, kServiceProgramId);
851  ASSERT_TRUE(program!= NULL);
852  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
853  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
854  program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
855                base::Bind(&ShaderCacheCb));
856  // Check that we got the good type, not the bad.
857  // Check Attribs
858  for (unsigned index = 0; index < kNumAttribs; ++index) {
859    const Program::VertexAttrib* attrib_info =
860        program->GetAttribInfo(index);
861    ASSERT_TRUE(attrib_info != NULL);
862    ShaderTranslator::VariableMap::const_iterator it = attrib_map.find(
863        attrib_info->name);
864    ASSERT_TRUE(it != attrib_map.end());
865    EXPECT_EQ(it->first, attrib_info->name);
866    EXPECT_EQ(static_cast<GLenum>(it->second.type), attrib_info->type);
867    EXPECT_EQ(it->second.size, attrib_info->size);
868    EXPECT_EQ(it->second.name, attrib_info->name);
869  }
870  // Check Uniforms
871  for (unsigned index = 0; index < kNumUniforms; ++index) {
872    const Program::UniformInfo* uniform_info =
873        program->GetUniformInfo(index);
874    ASSERT_TRUE(uniform_info != NULL);
875    ShaderTranslator::VariableMap::const_iterator it = uniform_map.find(
876        uniform_info->name);
877    ASSERT_TRUE(it != uniform_map.end());
878    EXPECT_EQ(it->first, uniform_info->name);
879    EXPECT_EQ(static_cast<GLenum>(it->second.type), uniform_info->type);
880    EXPECT_EQ(it->second.size, uniform_info->size);
881    EXPECT_EQ(it->second.name, uniform_info->name);
882  }
883}
884
885TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount) {
886  static const GLuint kClientProgramId = 124;
887  static const GLuint kServiceProgramId = 457;
888  Program* program = manager_.CreateProgram(
889      kClientProgramId, kServiceProgramId);
890  ASSERT_TRUE(program != NULL);
891  EXPECT_FALSE(program->CanLink());
892  const GLuint kVShaderClientId = 2001;
893  const GLuint kFShaderClientId = 2002;
894  const GLuint kVShaderServiceId = 3001;
895  const GLuint kFShaderServiceId = 3002;
896  Shader* vshader = shader_manager_.CreateShader(
897      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
898  ASSERT_TRUE(vshader != NULL);
899  TestHelper::SetShaderStates(gl_.get(), vshader, true);
900  Shader* fshader = shader_manager_.CreateShader(
901      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
902  ASSERT_TRUE(fshader != NULL);
903  TestHelper::SetShaderStates(gl_.get(), fshader, true);
904  EXPECT_FALSE(vshader->InUse());
905  EXPECT_FALSE(fshader->InUse());
906  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
907  EXPECT_TRUE(vshader->InUse());
908  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
909  EXPECT_TRUE(fshader->InUse());
910  EXPECT_TRUE(program->CanLink());
911  EXPECT_FALSE(program->InUse());
912  EXPECT_FALSE(program->IsDeleted());
913  manager_.UseProgram(program);
914  EXPECT_TRUE(program->InUse());
915  manager_.UseProgram(program);
916  EXPECT_TRUE(program->InUse());
917  manager_.MarkAsDeleted(&shader_manager_, program);
918  EXPECT_TRUE(program->IsDeleted());
919  Program* info2 = manager_.GetProgram(kClientProgramId);
920  EXPECT_EQ(program, info2);
921  manager_.UnuseProgram(&shader_manager_, program);
922  EXPECT_TRUE(program->InUse());
923  // this should delete the info.
924  EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId))
925      .Times(1)
926      .RetiresOnSaturation();
927  manager_.UnuseProgram(&shader_manager_, program);
928  info2 = manager_.GetProgram(kClientProgramId);
929  EXPECT_TRUE(info2 == NULL);
930  EXPECT_FALSE(vshader->InUse());
931  EXPECT_FALSE(fshader->InUse());
932}
933
934TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount2) {
935  static const GLuint kClientProgramId = 124;
936  static const GLuint kServiceProgramId = 457;
937  Program* program = manager_.CreateProgram(
938      kClientProgramId, kServiceProgramId);
939  ASSERT_TRUE(program != NULL);
940  EXPECT_FALSE(program->CanLink());
941  const GLuint kVShaderClientId = 2001;
942  const GLuint kFShaderClientId = 2002;
943  const GLuint kVShaderServiceId = 3001;
944  const GLuint kFShaderServiceId = 3002;
945  Shader* vshader = shader_manager_.CreateShader(
946      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
947  ASSERT_TRUE(vshader != NULL);
948  TestHelper::SetShaderStates(gl_.get(), vshader, true);
949  Shader* fshader = shader_manager_.CreateShader(
950      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
951  ASSERT_TRUE(fshader != NULL);
952  TestHelper::SetShaderStates(gl_.get(), fshader, true);
953  EXPECT_FALSE(vshader->InUse());
954  EXPECT_FALSE(fshader->InUse());
955  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
956  EXPECT_TRUE(vshader->InUse());
957  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
958  EXPECT_TRUE(fshader->InUse());
959  EXPECT_TRUE(program->CanLink());
960  EXPECT_FALSE(program->InUse());
961  EXPECT_FALSE(program->IsDeleted());
962  manager_.UseProgram(program);
963  EXPECT_TRUE(program->InUse());
964  manager_.UseProgram(program);
965  EXPECT_TRUE(program->InUse());
966  manager_.UnuseProgram(&shader_manager_, program);
967  EXPECT_TRUE(program->InUse());
968  manager_.UnuseProgram(&shader_manager_, program);
969  EXPECT_FALSE(program->InUse());
970  Program* info2 = manager_.GetProgram(kClientProgramId);
971  EXPECT_EQ(program, info2);
972  // this should delete the program.
973  EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId))
974      .Times(1)
975      .RetiresOnSaturation();
976  manager_.MarkAsDeleted(&shader_manager_, program);
977  info2 = manager_.GetProgram(kClientProgramId);
978  EXPECT_TRUE(info2 == NULL);
979  EXPECT_FALSE(vshader->InUse());
980  EXPECT_FALSE(fshader->InUse());
981}
982
983TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetProgramInfo) {
984  CommonDecoder::Bucket bucket;
985  const Program* program = manager_.GetProgram(kClientProgramId);
986  ASSERT_TRUE(program != NULL);
987  program->GetProgramInfo(&manager_, &bucket);
988  ProgramInfoHeader* header =
989      bucket.GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader));
990  ASSERT_TRUE(header != NULL);
991  EXPECT_EQ(1u, header->link_status);
992  EXPECT_EQ(arraysize(kAttribs), header->num_attribs);
993  EXPECT_EQ(arraysize(kUniforms), header->num_uniforms);
994  const ProgramInput* inputs = bucket.GetDataAs<const ProgramInput*>(
995      sizeof(*header),
996      sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
997  ASSERT_TRUE(inputs != NULL);
998  const ProgramInput* input = inputs;
999  // TODO(gman): Don't assume these are in order.
1000  for (uint32 ii = 0; ii < header->num_attribs; ++ii) {
1001    const AttribInfo& expected = kAttribs[ii];
1002    EXPECT_EQ(expected.size, input->size);
1003    EXPECT_EQ(expected.type, input->type);
1004    const int32* location = bucket.GetDataAs<const int32*>(
1005        input->location_offset, sizeof(int32));
1006    ASSERT_TRUE(location != NULL);
1007    EXPECT_EQ(expected.location, *location);
1008    const char* name_buf = bucket.GetDataAs<const char*>(
1009        input->name_offset, input->name_length);
1010    ASSERT_TRUE(name_buf != NULL);
1011    std::string name(name_buf, input->name_length);
1012    EXPECT_STREQ(expected.name, name.c_str());
1013    ++input;
1014  }
1015  // TODO(gman): Don't assume these are in order.
1016  for (uint32 ii = 0; ii < header->num_uniforms; ++ii) {
1017    const UniformInfo& expected = kUniforms[ii];
1018    EXPECT_EQ(expected.size, input->size);
1019    EXPECT_EQ(expected.type, input->type);
1020    const int32* locations = bucket.GetDataAs<const int32*>(
1021        input->location_offset, sizeof(int32) * input->size);
1022    ASSERT_TRUE(locations != NULL);
1023    for (int32 jj = 0; jj < input->size; ++jj) {
1024      EXPECT_EQ(
1025          ProgramManager::MakeFakeLocation(expected.fake_location, jj),
1026          locations[jj]);
1027    }
1028    const char* name_buf = bucket.GetDataAs<const char*>(
1029        input->name_offset, input->name_length);
1030    ASSERT_TRUE(name_buf != NULL);
1031    std::string name(name_buf, input->name_length);
1032    EXPECT_STREQ(expected.good_name, name.c_str());
1033    ++input;
1034  }
1035  EXPECT_EQ(header->num_attribs + header->num_uniforms,
1036            static_cast<uint32>(input - inputs));
1037}
1038
1039// Some drivers optimize out unused uniform array elements, so their
1040// location would be -1.
1041TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) {
1042  CommonDecoder::Bucket bucket;
1043  const Program* program = manager_.GetProgram(kClientProgramId);
1044  ASSERT_TRUE(program != NULL);
1045  // Emulate the situation that only the first element has a valid location.
1046  // TODO(zmo): Don't assume these are in order.
1047  for (size_t ii = 0; ii < arraysize(kUniforms); ++ii) {
1048    Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>(
1049        program->GetUniformInfo(ii));
1050    ASSERT_TRUE(uniform != NULL);
1051    EXPECT_EQ(static_cast<size_t>(kUniforms[ii].size),
1052              uniform->element_locations.size());
1053    for (GLsizei jj = 1; jj < uniform->size; ++jj)
1054      uniform->element_locations[jj] = -1;
1055  }
1056  program->GetProgramInfo(&manager_, &bucket);
1057  ProgramInfoHeader* header =
1058      bucket.GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader));
1059  ASSERT_TRUE(header != NULL);
1060  EXPECT_EQ(1u, header->link_status);
1061  EXPECT_EQ(arraysize(kAttribs), header->num_attribs);
1062  EXPECT_EQ(arraysize(kUniforms), header->num_uniforms);
1063  const ProgramInput* inputs = bucket.GetDataAs<const ProgramInput*>(
1064      sizeof(*header),
1065      sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
1066  ASSERT_TRUE(inputs != NULL);
1067  const ProgramInput* input = inputs + header->num_attribs;
1068  for (uint32 ii = 0; ii < header->num_uniforms; ++ii) {
1069    const UniformInfo& expected = kUniforms[ii];
1070    EXPECT_EQ(expected.size, input->size);
1071    const int32* locations = bucket.GetDataAs<const int32*>(
1072        input->location_offset, sizeof(int32) * input->size);
1073    ASSERT_TRUE(locations != NULL);
1074    EXPECT_EQ(
1075        ProgramManager::MakeFakeLocation(expected.fake_location, 0),
1076        locations[0]);
1077    for (int32 jj = 1; jj < input->size; ++jj)
1078      EXPECT_EQ(-1, locations[jj]);
1079    ++input;
1080  }
1081}
1082
1083TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) {
1084  // Set up shader
1085  const GLuint kVShaderClientId = 1;
1086  const GLuint kVShaderServiceId = 11;
1087  const GLuint kFShaderClientId = 2;
1088  const GLuint kFShaderServiceId = 12;
1089  ShaderTranslator::VariableMap attrib_map;
1090  for (uint32 ii = 0; ii < kNumAttribs; ++ii) {
1091    attrib_map[kAttribs[ii].name] = ShaderTranslatorInterface::VariableInfo(
1092        kAttribs[ii].type,
1093        kAttribs[ii].size,
1094        SH_PRECISION_MEDIUMP,
1095        kAttribStaticUse,
1096        kAttribs[ii].name);
1097  }
1098  // Check we can create shader.
1099  Shader* vshader = shader_manager_.CreateShader(
1100      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
1101  Shader* fshader = shader_manager_.CreateShader(
1102      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
1103  // Check shader got created.
1104  ASSERT_TRUE(vshader != NULL && fshader != NULL);
1105  // Set Status
1106  TestHelper::SetShaderStates(
1107      gl_.get(), vshader, true, NULL, NULL, &attrib_map, NULL, NULL, NULL);
1108  // Check attrib infos got copied.
1109  for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin();
1110       it != attrib_map.end(); ++it) {
1111    const Shader::VariableInfo* variable_info =
1112        vshader->GetAttribInfo(it->first);
1113    ASSERT_TRUE(variable_info != NULL);
1114    EXPECT_EQ(it->second.type, variable_info->type);
1115    EXPECT_EQ(it->second.size, variable_info->size);
1116    EXPECT_EQ(it->second.precision, variable_info->precision);
1117    EXPECT_EQ(it->second.static_use, variable_info->static_use);
1118    EXPECT_EQ(it->second.name, variable_info->name);
1119  }
1120  TestHelper::SetShaderStates(
1121      gl_.get(), fshader, true, NULL, NULL, &attrib_map, NULL, NULL, NULL);
1122
1123  // Set up program
1124  const GLuint kClientProgramId = 6666;
1125  const GLuint kServiceProgramId = 8888;
1126  Program* program =
1127      manager_.CreateProgram(kClientProgramId, kServiceProgramId);
1128  ASSERT_TRUE(program != NULL);
1129  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
1130  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
1131
1132  EXPECT_FALSE(program->DetectAttribLocationBindingConflicts());
1133  EXPECT_TRUE(LinkAsExpected(program, true));
1134
1135  program->SetAttribLocationBinding(kAttrib1Name, 0);
1136  EXPECT_FALSE(program->DetectAttribLocationBindingConflicts());
1137  EXPECT_TRUE(LinkAsExpected(program, true));
1138
1139  program->SetAttribLocationBinding("xxx", 0);
1140  EXPECT_FALSE(program->DetectAttribLocationBindingConflicts());
1141  EXPECT_TRUE(LinkAsExpected(program, true));
1142
1143  program->SetAttribLocationBinding(kAttrib2Name, 1);
1144  EXPECT_FALSE(program->DetectAttribLocationBindingConflicts());
1145  EXPECT_TRUE(LinkAsExpected(program, true));
1146
1147  program->SetAttribLocationBinding(kAttrib2Name, 0);
1148  EXPECT_TRUE(program->DetectAttribLocationBindingConflicts());
1149  EXPECT_TRUE(LinkAsExpected(program, false));
1150}
1151
1152TEST_F(ProgramManagerWithShaderTest, UniformsPrecisionMismatch) {
1153  // Set up shader
1154  const GLuint kVShaderClientId = 1;
1155  const GLuint kVShaderServiceId = 11;
1156  const GLuint kFShaderClientId = 2;
1157  const GLuint kFShaderServiceId = 12;
1158
1159  ShaderTranslator::VariableMap vertex_uniform_map;
1160  vertex_uniform_map["a"] = ShaderTranslator::VariableInfo(
1161      1, 3, SH_PRECISION_MEDIUMP, 1, "a");
1162  ShaderTranslator::VariableMap frag_uniform_map;
1163  frag_uniform_map["a"] = ShaderTranslator::VariableInfo(
1164      1, 3, SH_PRECISION_LOWP, 1, "a");
1165
1166  // Check we can create shader.
1167  Shader* vshader = shader_manager_.CreateShader(
1168      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
1169  Shader* fshader = shader_manager_.CreateShader(
1170      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
1171  // Check shader got created.
1172  ASSERT_TRUE(vshader != NULL && fshader != NULL);
1173  // Set Status
1174  TestHelper::SetShaderStates(
1175      gl_.get(), vshader, true, NULL, NULL, NULL,
1176      &vertex_uniform_map, NULL, NULL);
1177  TestHelper::SetShaderStates(
1178      gl_.get(), fshader, true, NULL, NULL, NULL,
1179      &frag_uniform_map, NULL, NULL);
1180
1181  // Set up program
1182  const GLuint kClientProgramId = 6666;
1183  const GLuint kServiceProgramId = 8888;
1184  Program* program =
1185      manager_.CreateProgram(kClientProgramId, kServiceProgramId);
1186  ASSERT_TRUE(program != NULL);
1187  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
1188  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
1189
1190  std::string conflicting_name;
1191
1192  EXPECT_TRUE(program->DetectUniformsMismatch(&conflicting_name));
1193  EXPECT_EQ("a", conflicting_name);
1194  EXPECT_TRUE(LinkAsExpected(program, false));
1195}
1196
1197// If a varying has different type in the vertex and fragment
1198// shader, linking should fail.
1199TEST_F(ProgramManagerWithShaderTest, VaryingTypeMismatch) {
1200  const VarInfo kVertexVarying =
1201      { GL_FLOAT_VEC3, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying };
1202  const VarInfo kFragmentVarying =
1203      { GL_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying };
1204  Program* program = SetupShaderVariableTest(
1205      &kVertexVarying, 1, &kFragmentVarying, 1);
1206
1207  std::string conflicting_name;
1208
1209  EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name));
1210  EXPECT_EQ("a", conflicting_name);
1211  EXPECT_TRUE(LinkAsExpected(program, false));
1212}
1213
1214// If a varying has different array size in the vertex and fragment
1215// shader, linking should fail.
1216TEST_F(ProgramManagerWithShaderTest, VaryingArraySizeMismatch) {
1217  const VarInfo kVertexVarying =
1218      { GL_FLOAT, 2, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying };
1219  const VarInfo kFragmentVarying =
1220      { GL_FLOAT, 3, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying };
1221  Program* program = SetupShaderVariableTest(
1222      &kVertexVarying, 1, &kFragmentVarying, 1);
1223
1224  std::string conflicting_name;
1225
1226  EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name));
1227  EXPECT_EQ("a", conflicting_name);
1228  EXPECT_TRUE(LinkAsExpected(program, false));
1229}
1230
1231// If a varying has different precision in the vertex and fragment
1232// shader, linking should succeed.
1233TEST_F(ProgramManagerWithShaderTest, VaryingPrecisionMismatch) {
1234  const VarInfo kVertexVarying =
1235      { GL_FLOAT, 2, SH_PRECISION_HIGHP, 1, "a", kVarVarying };
1236  const VarInfo kFragmentVarying =
1237      { GL_FLOAT, 2, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying };
1238  Program* program = SetupShaderVariableTest(
1239      &kVertexVarying, 1, &kFragmentVarying, 1);
1240
1241  std::string conflicting_name;
1242
1243  EXPECT_FALSE(program->DetectVaryingsMismatch(&conflicting_name));
1244  EXPECT_TRUE(conflicting_name.empty());
1245  EXPECT_TRUE(LinkAsExpected(program, true));
1246}
1247
1248// If a varying is statically used in fragment shader but not
1249// declared in vertex shader, link should fail.
1250TEST_F(ProgramManagerWithShaderTest, VaryingMissing) {
1251  const VarInfo kFragmentVarying =
1252      { GL_FLOAT, 3, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying };
1253  Program* program = SetupShaderVariableTest(
1254      NULL, 0, &kFragmentVarying, 1);
1255
1256  std::string conflicting_name;
1257
1258  EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name));
1259  EXPECT_EQ("a", conflicting_name);
1260  EXPECT_TRUE(LinkAsExpected(program, false));
1261}
1262
1263// If a varying is declared but not statically used in fragment
1264// shader, even if it's not declared in vertex shader, link should
1265// succeed.
1266TEST_F(ProgramManagerWithShaderTest, InactiveVarying) {
1267  const VarInfo kFragmentVarying =
1268      { GL_FLOAT, 3, SH_PRECISION_MEDIUMP, 0, "a", kVarVarying };
1269  Program* program = SetupShaderVariableTest(
1270      NULL, 0, &kFragmentVarying, 1);
1271
1272  std::string conflicting_name;
1273
1274  EXPECT_FALSE(program->DetectVaryingsMismatch(&conflicting_name));
1275  EXPECT_TRUE(conflicting_name.empty());
1276  EXPECT_TRUE(LinkAsExpected(program, true));
1277}
1278
1279// Uniforms and attributes are both global variables, thus sharing
1280// the same namespace. Any name conflicts should cause link
1281// failure.
1282TEST_F(ProgramManagerWithShaderTest, AttribUniformNameConflict) {
1283  const VarInfo kVertexAttribute =
1284      { GL_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarAttribute };
1285  const VarInfo kFragmentUniform =
1286      { GL_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarUniform };
1287  Program* program = SetupShaderVariableTest(
1288      &kVertexAttribute, 1, &kFragmentUniform, 1);
1289
1290  std::string conflicting_name;
1291
1292  EXPECT_TRUE(program->DetectGlobalNameConflicts(&conflicting_name));
1293  EXPECT_EQ("a", conflicting_name);
1294  EXPECT_TRUE(LinkAsExpected(program, false));
1295}
1296
1297// Varyings go over 8 rows.
1298TEST_F(ProgramManagerWithShaderTest, TooManyVaryings) {
1299  const VarInfo kVertexVaryings[] = {
1300      { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying },
1301      { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying }
1302  };
1303  const VarInfo kFragmentVaryings[] = {
1304      { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying },
1305      { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying }
1306  };
1307  Program* program = SetupShaderVariableTest(
1308      kVertexVaryings, 2, kFragmentVaryings, 2);
1309
1310  EXPECT_FALSE(
1311      program->CheckVaryingsPacking(Program::kCountOnlyStaticallyUsed));
1312  EXPECT_TRUE(LinkAsExpected(program, false));
1313}
1314
1315// Varyings go over 8 rows but some are inactive
1316TEST_F(ProgramManagerWithShaderTest, TooManyInactiveVaryings) {
1317  const VarInfo kVertexVaryings[] = {
1318      { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying },
1319      { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying }
1320  };
1321  const VarInfo kFragmentVaryings[] = {
1322      { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 0, "a", kVarVarying },
1323      { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying }
1324  };
1325  Program* program = SetupShaderVariableTest(
1326      kVertexVaryings, 2, kFragmentVaryings, 2);
1327
1328  EXPECT_TRUE(
1329      program->CheckVaryingsPacking(Program::kCountOnlyStaticallyUsed));
1330  EXPECT_TRUE(LinkAsExpected(program, true));
1331}
1332
1333// Varyings go over 8 rows but some are inactive.
1334// However, we still fail the check if kCountAll option is used.
1335TEST_F(ProgramManagerWithShaderTest, CountAllVaryingsInPacking) {
1336  const VarInfo kVertexVaryings[] = {
1337      { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying },
1338      { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying }
1339  };
1340  const VarInfo kFragmentVaryings[] = {
1341      { GL_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 0, "a", kVarVarying },
1342      { GL_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying }
1343  };
1344  Program* program = SetupShaderVariableTest(
1345      kVertexVaryings, 2, kFragmentVaryings, 2);
1346
1347  EXPECT_FALSE(program->CheckVaryingsPacking(Program::kCountAll));
1348}
1349
1350TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) {
1351  const GLuint kVShaderClientId = 2001;
1352  const GLuint kFShaderClientId = 2002;
1353  const GLuint kVShaderServiceId = 3001;
1354  const GLuint kFShaderServiceId = 3002;
1355  Shader* vshader = shader_manager_.CreateShader(
1356      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
1357  ASSERT_TRUE(vshader != NULL);
1358  TestHelper::SetShaderStates(gl_.get(), vshader, true);
1359  Shader* fshader = shader_manager_.CreateShader(
1360      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
1361  ASSERT_TRUE(fshader != NULL);
1362  TestHelper::SetShaderStates(gl_.get(), fshader, true);
1363  static const GLuint kClientProgramId = 1234;
1364  static const GLuint kServiceProgramId = 5679;
1365  Program* program = manager_.CreateProgram(
1366      kClientProgramId, kServiceProgramId);
1367  ASSERT_TRUE(program != NULL);
1368  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
1369  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
1370
1371  static const GLenum kSamplerTypes[] = {
1372    GL_SAMPLER_2D,
1373    GL_SAMPLER_CUBE,
1374    GL_SAMPLER_EXTERNAL_OES,
1375    GL_SAMPLER_3D_OES,
1376    GL_SAMPLER_2D_RECT_ARB,
1377  };
1378  const size_t kNumSamplerTypes = arraysize(kSamplerTypes);
1379  for (size_t ii = 0; ii < kNumSamplerTypes; ++ii) {
1380    static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = {
1381      { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
1382      { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, },
1383      { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
1384    };
1385    ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
1386      { kUniform1Name,
1387        kUniform1Size,
1388        kUniform1Type,
1389        kUniform1FakeLocation,
1390        kUniform1RealLocation,
1391        kUniform1DesiredLocation,
1392        kUniform1Name,
1393      },
1394      { kUniform2Name,
1395        kUniform2Size,
1396        kSamplerTypes[ii],
1397        kUniform2FakeLocation,
1398        kUniform2RealLocation,
1399        kUniform2DesiredLocation,
1400        kUniform2Name,
1401      },
1402      { kUniform3BadName,
1403        kUniform3Size,
1404        kUniform3Type,
1405        kUniform3FakeLocation,
1406        kUniform3RealLocation,
1407        kUniform3DesiredLocation,
1408        kUniform3GoodName,
1409      },
1410    };
1411    const size_t kNumAttribs = arraysize(kAttribs);
1412    const size_t kNumUniforms = arraysize(kUniforms);
1413    SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
1414                kServiceProgramId);
1415    program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
1416                  base::Bind(&ShaderCacheCb));
1417    SetupExpectationsForClearingUniforms(kUniforms, kNumUniforms);
1418    manager_.ClearUniforms(program);
1419  }
1420}
1421
1422TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) {
1423  const GLuint kVShaderClientId = 2001;
1424  const GLuint kFShaderClientId = 2002;
1425  const GLuint kVShaderServiceId = 3001;
1426  const GLuint kFShaderServiceId = 3002;
1427
1428  const GLint kUniform1DesiredLocation = 10;
1429  const GLint kUniform2DesiredLocation = -1;
1430  const GLint kUniform3DesiredLocation = 5;
1431
1432  Shader* vshader = shader_manager_.CreateShader(
1433      kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
1434  ASSERT_TRUE(vshader != NULL);
1435  TestHelper::SetShaderStates(gl_.get(), vshader, true);
1436  Shader* fshader = shader_manager_.CreateShader(
1437      kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
1438  ASSERT_TRUE(fshader != NULL);
1439  TestHelper::SetShaderStates(gl_.get(), fshader, true);
1440  static const GLuint kClientProgramId = 1234;
1441  static const GLuint kServiceProgramId = 5679;
1442  Program* program = manager_.CreateProgram(
1443      kClientProgramId, kServiceProgramId);
1444  ASSERT_TRUE(program != NULL);
1445  EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
1446  EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
1447  EXPECT_TRUE(program->SetUniformLocationBinding(
1448      kUniform1Name, kUniform1DesiredLocation));
1449  EXPECT_TRUE(program->SetUniformLocationBinding(
1450      kUniform3BadName, kUniform3DesiredLocation));
1451
1452  static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = {
1453    { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
1454    { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, },
1455    { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
1456  };
1457  ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
1458    { kUniform1Name,
1459      kUniform1Size,
1460      kUniform1Type,
1461      kUniform1FakeLocation,
1462      kUniform1RealLocation,
1463      kUniform1DesiredLocation,
1464      kUniform1Name,
1465    },
1466    { kUniform2Name,
1467      kUniform2Size,
1468      kUniform2Type,
1469      kUniform2FakeLocation,
1470      kUniform2RealLocation,
1471      kUniform2DesiredLocation,
1472      kUniform2Name,
1473    },
1474    { kUniform3BadName,
1475      kUniform3Size,
1476      kUniform3Type,
1477      kUniform3FakeLocation,
1478      kUniform3RealLocation,
1479      kUniform3DesiredLocation,
1480      kUniform3GoodName,
1481    },
1482  };
1483
1484  const size_t kNumAttribs = arraysize(kAttribs);
1485  const size_t kNumUniforms = arraysize(kUniforms);
1486  SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
1487              kServiceProgramId);
1488  program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
1489                base::Bind(&ShaderCacheCb));
1490
1491  EXPECT_EQ(kUniform1DesiredLocation,
1492            program->GetUniformFakeLocation(kUniform1Name));
1493  EXPECT_EQ(kUniform3DesiredLocation,
1494            program->GetUniformFakeLocation(kUniform3BadName));
1495  EXPECT_EQ(kUniform3DesiredLocation,
1496            program->GetUniformFakeLocation(kUniform3GoodName));
1497}
1498
1499class ProgramManagerWithCacheTest : public GpuServiceTest {
1500 public:
1501  static const GLuint kClientProgramId = 1;
1502  static const GLuint kServiceProgramId = 10;
1503  static const GLuint kVertexShaderClientId = 2;
1504  static const GLuint kFragmentShaderClientId = 20;
1505  static const GLuint kVertexShaderServiceId = 3;
1506  static const GLuint kFragmentShaderServiceId = 30;
1507
1508  ProgramManagerWithCacheTest()
1509      : cache_(new MockProgramCache()),
1510        manager_(cache_.get(), kMaxVaryingVectors),
1511        vertex_shader_(NULL),
1512        fragment_shader_(NULL),
1513        program_(NULL) {
1514  }
1515  virtual ~ProgramManagerWithCacheTest() {
1516    manager_.Destroy(false);
1517    shader_manager_.Destroy(false);
1518  }
1519
1520 protected:
1521  virtual void SetUp() {
1522    GpuServiceTest::SetUp();
1523
1524    vertex_shader_ = shader_manager_.CreateShader(
1525       kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
1526    fragment_shader_ = shader_manager_.CreateShader(
1527       kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
1528    ASSERT_TRUE(vertex_shader_ != NULL);
1529    ASSERT_TRUE(fragment_shader_ != NULL);
1530    vertex_shader_->set_source("lka asjf bjajsdfj");
1531    fragment_shader_->set_source("lka asjf a   fasgag 3rdsf3 bjajsdfj");
1532
1533    program_ = manager_.CreateProgram(
1534        kClientProgramId, kServiceProgramId);
1535    ASSERT_TRUE(program_ != NULL);
1536
1537    program_->AttachShader(&shader_manager_, vertex_shader_);
1538    program_->AttachShader(&shader_manager_, fragment_shader_);
1539  }
1540
1541  void SetShadersCompiled() {
1542    TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true);
1543    TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
1544  }
1545
1546  void SetProgramCached() {
1547    cache_->LinkedProgramCacheSuccess(
1548        vertex_shader_->source(),
1549        NULL,
1550        fragment_shader_->source(),
1551        NULL,
1552        &program_->bind_attrib_location_map());
1553  }
1554
1555  void SetExpectationsForProgramCached() {
1556    SetExpectationsForProgramCached(program_,
1557                                    vertex_shader_,
1558                                    fragment_shader_);
1559  }
1560
1561  void SetExpectationsForProgramCached(
1562      Program* program,
1563      Shader* vertex_shader,
1564      Shader* fragment_shader) {
1565    EXPECT_CALL(*cache_.get(), SaveLinkedProgram(
1566        program->service_id(),
1567        vertex_shader,
1568        NULL,
1569        fragment_shader,
1570        NULL,
1571        &program->bind_attrib_location_map(),
1572        _)).Times(1);
1573  }
1574
1575  void SetExpectationsForNotCachingProgram() {
1576    SetExpectationsForNotCachingProgram(program_,
1577                                        vertex_shader_,
1578                                        fragment_shader_);
1579  }
1580
1581  void SetExpectationsForNotCachingProgram(
1582      Program* program,
1583      Shader* vertex_shader,
1584      Shader* fragment_shader) {
1585    EXPECT_CALL(*cache_.get(), SaveLinkedProgram(
1586        program->service_id(),
1587        vertex_shader,
1588        NULL,
1589        fragment_shader,
1590        NULL,
1591        &program->bind_attrib_location_map(),
1592        _)).Times(0);
1593  }
1594
1595  void SetExpectationsForProgramLoad(ProgramCache::ProgramLoadResult result) {
1596    SetExpectationsForProgramLoad(kServiceProgramId,
1597                                  program_,
1598                                  vertex_shader_,
1599                                  fragment_shader_,
1600                                  result);
1601  }
1602
1603  void SetExpectationsForProgramLoad(
1604      GLuint service_program_id,
1605      Program* program,
1606      Shader* vertex_shader,
1607      Shader* fragment_shader,
1608      ProgramCache::ProgramLoadResult result) {
1609    EXPECT_CALL(*cache_.get(),
1610                LoadLinkedProgram(service_program_id,
1611                                  vertex_shader,
1612                                  NULL,
1613                                  fragment_shader,
1614                                  NULL,
1615                                  &program->bind_attrib_location_map(),
1616                                  _))
1617        .WillOnce(Return(result));
1618  }
1619
1620  void SetExpectationsForProgramLoadSuccess() {
1621    SetExpectationsForProgramLoadSuccess(kServiceProgramId);
1622  }
1623
1624  void SetExpectationsForProgramLoadSuccess(GLuint service_program_id) {
1625    TestHelper::SetupProgramSuccessExpectations(gl_.get(),
1626                                                NULL,
1627                                                0,
1628                                                NULL,
1629                                                0,
1630                                                service_program_id);
1631  }
1632
1633  void SetExpectationsForProgramLink() {
1634    SetExpectationsForProgramLink(kServiceProgramId);
1635  }
1636
1637  void SetExpectationsForProgramLink(GLuint service_program_id) {
1638    TestHelper::SetupShader(gl_.get(), NULL, 0, NULL, 0, service_program_id);
1639    if (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) {
1640      EXPECT_CALL(*gl_.get(),
1641                  ProgramParameteri(service_program_id,
1642                                    PROGRAM_BINARY_RETRIEVABLE_HINT,
1643                                    GL_TRUE)).Times(1);
1644    }
1645  }
1646
1647  void SetExpectationsForSuccessCompile(
1648      const Shader* shader) {
1649    const GLuint shader_id = shader->service_id();
1650    const char* src = shader->source().c_str();
1651    EXPECT_CALL(*gl_.get(),
1652                ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1);
1653    EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1);
1654    EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _))
1655        .WillOnce(SetArgumentPointee<2>(GL_TRUE));
1656  }
1657
1658  void SetExpectationsForNoCompile(const Shader* shader) {
1659    const GLuint shader_id = shader->service_id();
1660    const char* src = shader->source().c_str();
1661    EXPECT_CALL(*gl_.get(),
1662                ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0);
1663    EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0);
1664    EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _))
1665        .Times(0);
1666  }
1667
1668  void SetExpectationsForErrorCompile(const Shader* shader) {
1669    const GLuint shader_id = shader->service_id();
1670    const char* src = shader->source().c_str();
1671    EXPECT_CALL(*gl_.get(),
1672                ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1);
1673    EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1);
1674    EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _))
1675        .WillOnce(SetArgumentPointee<2>(GL_FALSE));
1676    EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _))
1677        .WillOnce(SetArgumentPointee<2>(0));
1678    EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _))
1679        .Times(1);
1680  }
1681
1682  scoped_ptr<MockProgramCache> cache_;
1683  ProgramManager manager_;
1684
1685  Shader* vertex_shader_;
1686  Shader* fragment_shader_;
1687  Program* program_;
1688  ShaderManager shader_manager_;
1689};
1690
1691// GCC requires these declarations, but MSVC requires they not be present
1692#ifndef COMPILER_MSVC
1693const GLuint ProgramManagerWithCacheTest::kClientProgramId;
1694const GLuint ProgramManagerWithCacheTest::kServiceProgramId;
1695const GLuint ProgramManagerWithCacheTest::kVertexShaderClientId;
1696const GLuint ProgramManagerWithCacheTest::kFragmentShaderClientId;
1697const GLuint ProgramManagerWithCacheTest::kVertexShaderServiceId;
1698const GLuint ProgramManagerWithCacheTest::kFragmentShaderServiceId;
1699#endif
1700
1701TEST_F(ProgramManagerWithCacheTest, CacheProgramOnSuccessfulLink) {
1702  SetShadersCompiled();
1703  SetExpectationsForProgramLink();
1704  SetExpectationsForProgramCached();
1705  EXPECT_TRUE(program_->Link(NULL, NULL, NULL,
1706      Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb)));
1707}
1708
1709TEST_F(ProgramManagerWithCacheTest, LoadProgramOnProgramCacheHit) {
1710  SetShadersCompiled();
1711  SetProgramCached();
1712
1713  SetExpectationsForNoCompile(vertex_shader_);
1714  SetExpectationsForNoCompile(fragment_shader_);
1715  SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS);
1716  SetExpectationsForNotCachingProgram();
1717  SetExpectationsForProgramLoadSuccess();
1718
1719  EXPECT_TRUE(program_->Link(NULL, NULL, NULL,
1720      Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb)));
1721}
1722
1723}  // namespace gles2
1724}  // namespace gpu
1725