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/shader_manager.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "gpu/command_buffer/service/gpu_service_test.h"
9#include "gpu/command_buffer/service/mocks.h"
10#include "gpu/command_buffer/service/test_helper.h"
11#include "testing/gtest/include/gtest/gtest.h"
12#include "ui/gl/gl_mock.h"
13
14using ::testing::Return;
15using ::testing::ReturnRef;
16
17namespace gpu {
18namespace gles2 {
19
20class ShaderManagerTest : public GpuServiceTest {
21 public:
22  ShaderManagerTest() {
23  }
24
25  virtual ~ShaderManagerTest() {
26    manager_.Destroy(false);
27  }
28
29 protected:
30  ShaderManager manager_;
31};
32
33TEST_F(ShaderManagerTest, Basic) {
34  const GLuint kClient1Id = 1;
35  const GLuint kService1Id = 11;
36  const GLenum kShader1Type = GL_VERTEX_SHADER;
37  const GLuint kClient2Id = 2;
38  // Check we can create shader.
39  Shader* info0 = manager_.CreateShader(
40      kClient1Id, kService1Id, kShader1Type);
41  // Check shader got created.
42  ASSERT_TRUE(info0 != NULL);
43  Shader* shader1 = manager_.GetShader(kClient1Id);
44  ASSERT_EQ(info0, shader1);
45  // Check we get nothing for a non-existent shader.
46  EXPECT_TRUE(manager_.GetShader(kClient2Id) == NULL);
47  // Check we can't get the shader after we remove it.
48  manager_.MarkAsDeleted(shader1);
49  EXPECT_TRUE(manager_.GetShader(kClient1Id) == NULL);
50}
51
52TEST_F(ShaderManagerTest, Destroy) {
53  const GLuint kClient1Id = 1;
54  const GLuint kService1Id = 11;
55  const GLenum kShader1Type = GL_VERTEX_SHADER;
56  // Check we can create shader.
57  Shader* shader1 = manager_.CreateShader(
58      kClient1Id, kService1Id, kShader1Type);
59  // Check shader got created.
60  ASSERT_TRUE(shader1 != NULL);
61  EXPECT_CALL(*gl_, DeleteShader(kService1Id))
62      .Times(1)
63      .RetiresOnSaturation();
64  manager_.Destroy(true);
65  // Check that resources got freed.
66  shader1 = manager_.GetShader(kClient1Id);
67  ASSERT_TRUE(shader1 == NULL);
68}
69
70TEST_F(ShaderManagerTest, DeleteBug) {
71  const GLuint kClient1Id = 1;
72  const GLuint kClient2Id = 2;
73  const GLuint kService1Id = 11;
74  const GLuint kService2Id = 12;
75  const GLenum kShaderType = GL_VERTEX_SHADER;
76  // Check we can create shader.
77  scoped_refptr<Shader> shader1(
78      manager_.CreateShader(kClient1Id, kService1Id, kShaderType));
79  scoped_refptr<Shader> shader2(
80      manager_.CreateShader(kClient2Id, kService2Id, kShaderType));
81  ASSERT_TRUE(shader1.get());
82  ASSERT_TRUE(shader2.get());
83  manager_.UseShader(shader1.get());
84  manager_.MarkAsDeleted(shader1.get());
85  manager_.MarkAsDeleted(shader2.get());
86  EXPECT_TRUE(manager_.IsOwned(shader1.get()));
87  EXPECT_FALSE(manager_.IsOwned(shader2.get()));
88}
89
90TEST_F(ShaderManagerTest, DoCompile) {
91  const GLuint kClient1Id = 1;
92  const GLuint kService1Id = 11;
93  const GLenum kShader1Type = GL_VERTEX_SHADER;
94  const char* kClient1Source = "hello world";
95  const GLenum kAttrib1Type = GL_FLOAT_VEC2;
96  const GLsizei kAttrib1Size = 2;
97  const int kAttrib1Precision = SH_PRECISION_MEDIUMP;
98  const char* kAttrib1Name = "attr1";
99  const GLenum kAttrib2Type = GL_FLOAT_VEC3;
100  const GLsizei kAttrib2Size = 4;
101  const int kAttrib2Precision = SH_PRECISION_HIGHP;
102  const char* kAttrib2Name = "attr2";
103  const int kAttribStaticUse = 0;
104  const GLenum kUniform1Type = GL_FLOAT_MAT2;
105  const GLsizei kUniform1Size = 3;
106  const int kUniform1Precision = SH_PRECISION_LOWP;
107  const int kUniform1StaticUse = 1;
108  const char* kUniform1Name = "uni1";
109  const GLenum kUniform2Type = GL_FLOAT_MAT3;
110  const GLsizei kUniform2Size = 5;
111  const int kUniform2Precision = SH_PRECISION_MEDIUMP;
112  const int kUniform2StaticUse = 0;
113  const char* kUniform2Name = "uni2";
114  const GLenum kVarying1Type = GL_FLOAT_VEC4;
115  const GLsizei kVarying1Size = 1;
116  const int kVarying1Precision = SH_PRECISION_HIGHP;
117  const int kVarying1StaticUse = 0;
118  const char* kVarying1Name = "varying1";
119
120  // Check we can create shader.
121  Shader* shader1 = manager_.CreateShader(
122      kClient1Id, kService1Id, kShader1Type);
123  // Check shader got created.
124  ASSERT_TRUE(shader1 != NULL);
125  EXPECT_EQ(kService1Id, shader1->service_id());
126  // Check if the shader has correct type.
127  EXPECT_EQ(kShader1Type, shader1->shader_type());
128  EXPECT_FALSE(shader1->valid());
129  EXPECT_FALSE(shader1->InUse());
130  EXPECT_TRUE(shader1->source().empty());
131  EXPECT_TRUE(shader1->log_info().empty());
132  EXPECT_TRUE(shader1->signature_source().empty());
133  EXPECT_TRUE(shader1->translated_source().empty());
134  EXPECT_EQ(0u, shader1->attrib_map().size());
135  EXPECT_EQ(0u, shader1->uniform_map().size());
136  EXPECT_EQ(0u, shader1->varying_map().size());
137
138  // Check we can set its source.
139  shader1->set_source(kClient1Source);
140  EXPECT_STREQ(kClient1Source, shader1->source().c_str());
141  EXPECT_TRUE(shader1->signature_source().empty());
142
143  // Check DoCompile() will set compilation states, log, translated source,
144  // shader variables, and name mapping.
145  const std::string kLog = "foo";
146  const std::string kTranslatedSource = "poo";
147
148  ShaderTranslator::VariableMap attrib_map;
149  attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo(
150      kAttrib1Type, kAttrib1Size, kAttrib1Precision,
151      kAttribStaticUse, kAttrib1Name);
152  attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo(
153      kAttrib2Type, kAttrib2Size, kAttrib2Precision,
154      kAttribStaticUse, kAttrib2Name);
155  ShaderTranslator::VariableMap uniform_map;
156  uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo(
157      kUniform1Type, kUniform1Size, kUniform1Precision,
158      kUniform1StaticUse, kUniform1Name);
159  uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo(
160      kUniform2Type, kUniform2Size, kUniform2Precision,
161      kUniform2StaticUse, kUniform2Name);
162  ShaderTranslator::VariableMap varying_map;
163  varying_map[kVarying1Name] = ShaderTranslatorInterface::VariableInfo(
164      kVarying1Type, kVarying1Size, kVarying1Precision,
165      kVarying1StaticUse, kVarying1Name);
166
167  TestHelper::SetShaderStates(
168      gl_.get(), shader1, true, &kLog, &kTranslatedSource,
169      &attrib_map, &uniform_map, &varying_map, NULL);
170  EXPECT_TRUE(shader1->valid());
171  // When compilation succeeds, no log is recorded.
172  EXPECT_STREQ("", shader1->log_info().c_str());
173  EXPECT_STREQ(kClient1Source, shader1->signature_source().c_str());
174  EXPECT_STREQ(kTranslatedSource.c_str(), shader1->translated_source().c_str());
175
176  // Check varying infos got copied.
177  EXPECT_EQ(attrib_map.size(), shader1->attrib_map().size());
178  for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin();
179       it != attrib_map.end(); ++it) {
180    const Shader::VariableInfo* variable_info =
181        shader1->GetAttribInfo(it->first);
182    ASSERT_TRUE(variable_info != NULL);
183    EXPECT_EQ(it->second.type, variable_info->type);
184    EXPECT_EQ(it->second.size, variable_info->size);
185    EXPECT_EQ(it->second.precision, variable_info->precision);
186    EXPECT_EQ(it->second.static_use, variable_info->static_use);
187    EXPECT_STREQ(it->second.name.c_str(), variable_info->name.c_str());
188  }
189  // Check uniform infos got copied.
190  EXPECT_EQ(uniform_map.size(), shader1->uniform_map().size());
191  for (ShaderTranslator::VariableMap::const_iterator it = uniform_map.begin();
192       it != uniform_map.end(); ++it) {
193    const Shader::VariableInfo* variable_info =
194        shader1->GetUniformInfo(it->first);
195    ASSERT_TRUE(variable_info != NULL);
196    EXPECT_EQ(it->second.type, variable_info->type);
197    EXPECT_EQ(it->second.size, variable_info->size);
198    EXPECT_EQ(it->second.precision, variable_info->precision);
199    EXPECT_EQ(it->second.static_use, variable_info->static_use);
200    EXPECT_STREQ(it->second.name.c_str(), variable_info->name.c_str());
201  }
202  // Check varying infos got copied.
203  EXPECT_EQ(varying_map.size(), shader1->varying_map().size());
204  for (ShaderTranslator::VariableMap::const_iterator it = varying_map.begin();
205       it != varying_map.end(); ++it) {
206    const Shader::VariableInfo* variable_info =
207        shader1->GetVaryingInfo(it->first);
208    ASSERT_TRUE(variable_info != NULL);
209    EXPECT_EQ(it->second.type, variable_info->type);
210    EXPECT_EQ(it->second.size, variable_info->size);
211    EXPECT_EQ(it->second.precision, variable_info->precision);
212    EXPECT_EQ(it->second.static_use, variable_info->static_use);
213    EXPECT_STREQ(it->second.name.c_str(), variable_info->name.c_str());
214  }
215
216  // Compile failure case.
217  TestHelper::SetShaderStates(
218      gl_.get(), shader1, false, &kLog, &kTranslatedSource,
219      &attrib_map, &uniform_map, &varying_map, NULL);
220  EXPECT_FALSE(shader1->valid());
221  EXPECT_STREQ(kLog.c_str(), shader1->log_info().c_str());
222  EXPECT_STREQ("", shader1->translated_source().c_str());
223  EXPECT_TRUE(shader1->attrib_map().empty());
224  EXPECT_TRUE(shader1->uniform_map().empty());
225  EXPECT_TRUE(shader1->varying_map().empty());
226}
227
228TEST_F(ShaderManagerTest, ShaderInfoUseCount) {
229  const GLuint kClient1Id = 1;
230  const GLuint kService1Id = 11;
231  const GLenum kShader1Type = GL_VERTEX_SHADER;
232  // Check we can create shader.
233  Shader* shader1 = manager_.CreateShader(
234      kClient1Id, kService1Id, kShader1Type);
235  // Check shader got created.
236  ASSERT_TRUE(shader1 != NULL);
237  EXPECT_FALSE(shader1->InUse());
238  EXPECT_FALSE(shader1->IsDeleted());
239  manager_.UseShader(shader1);
240  EXPECT_TRUE(shader1->InUse());
241  manager_.UseShader(shader1);
242  EXPECT_TRUE(shader1->InUse());
243  manager_.MarkAsDeleted(shader1);
244  EXPECT_TRUE(shader1->IsDeleted());
245  Shader* shader2 = manager_.GetShader(kClient1Id);
246  EXPECT_EQ(shader1, shader2);
247  manager_.UnuseShader(shader1);
248  EXPECT_TRUE(shader1->InUse());
249  manager_.UnuseShader(shader1);  // this should delete the info.
250  shader2 = manager_.GetShader(kClient1Id);
251  EXPECT_TRUE(shader2 == NULL);
252
253  shader1 = manager_.CreateShader(kClient1Id, kService1Id, kShader1Type);
254  ASSERT_TRUE(shader1 != NULL);
255  EXPECT_FALSE(shader1->InUse());
256  manager_.UseShader(shader1);
257  EXPECT_TRUE(shader1->InUse());
258  manager_.UseShader(shader1);
259  EXPECT_TRUE(shader1->InUse());
260  manager_.UnuseShader(shader1);
261  EXPECT_TRUE(shader1->InUse());
262  manager_.UnuseShader(shader1);
263  EXPECT_FALSE(shader1->InUse());
264  shader2 = manager_.GetShader(kClient1Id);
265  EXPECT_EQ(shader1, shader2);
266  manager_.MarkAsDeleted(shader1);  // this should delete the shader.
267  shader2 = manager_.GetShader(kClient1Id);
268  EXPECT_TRUE(shader2 == NULL);
269}
270
271}  // namespace gles2
272}  // namespace gpu
273