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