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