1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/shader_manager.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "gpu/command_buffer/service/mocks.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/gl/gl_mock.h"
12 using ::testing::Return;
13 using ::testing::ReturnRef;
18 class ShaderManagerTest : public testing::Test {
23 virtual ~ShaderManagerTest() {
24 manager_.Destroy(false);
28 virtual void SetUp() {
29 gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
30 ::gfx::GLInterface::SetGLInterface(gl_.get());
33 virtual void TearDown() {
34 ::gfx::GLInterface::SetGLInterface(NULL);
38 // Use StrictMock to make 100% sure we know how GL will be called.
39 scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
40 ShaderManager manager_;
43 TEST_F(ShaderManagerTest, Basic) {
44 const GLuint kClient1Id = 1;
45 const GLuint kService1Id = 11;
46 const GLenum kShader1Type = GL_VERTEX_SHADER;
47 const GLuint kClient2Id = 2;
48 // Check we can create shader.
49 Shader* info0 = manager_.CreateShader(
50 kClient1Id, kService1Id, kShader1Type);
51 // Check shader got created.
52 ASSERT_TRUE(info0 != NULL);
53 Shader* shader1 = manager_.GetShader(kClient1Id);
54 ASSERT_EQ(info0, shader1);
55 // Check we get nothing for a non-existent shader.
56 EXPECT_TRUE(manager_.GetShader(kClient2Id) == NULL);
57 // Check we can't get the shader after we remove it.
58 manager_.MarkAsDeleted(shader1);
59 EXPECT_TRUE(manager_.GetShader(kClient1Id) == NULL);
62 TEST_F(ShaderManagerTest, Destroy) {
63 const GLuint kClient1Id = 1;
64 const GLuint kService1Id = 11;
65 const GLenum kShader1Type = GL_VERTEX_SHADER;
66 // Check we can create shader.
67 Shader* shader1 = manager_.CreateShader(
68 kClient1Id, kService1Id, kShader1Type);
69 // Check shader got created.
70 ASSERT_TRUE(shader1 != NULL);
71 EXPECT_CALL(*gl_, DeleteShader(kService1Id))
73 .RetiresOnSaturation();
74 manager_.Destroy(true);
75 // Check that resources got freed.
76 shader1 = manager_.GetShader(kClient1Id);
77 ASSERT_TRUE(shader1 == NULL);
80 TEST_F(ShaderManagerTest, DeleteBug) {
81 const GLuint kClient1Id = 1;
82 const GLuint kClient2Id = 2;
83 const GLuint kService1Id = 11;
84 const GLuint kService2Id = 12;
85 const GLenum kShaderType = GL_VERTEX_SHADER;
86 // Check we can create shader.
87 scoped_refptr<Shader> shader1(
88 manager_.CreateShader(kClient1Id, kService1Id, kShaderType));
89 scoped_refptr<Shader> shader2(
90 manager_.CreateShader(kClient2Id, kService2Id, kShaderType));
91 ASSERT_TRUE(shader1.get());
92 ASSERT_TRUE(shader2.get());
93 manager_.UseShader(shader1.get());
94 manager_.MarkAsDeleted(shader1.get());
95 manager_.MarkAsDeleted(shader2.get());
96 EXPECT_TRUE(manager_.IsOwned(shader1.get()));
97 EXPECT_FALSE(manager_.IsOwned(shader2.get()));
100 TEST_F(ShaderManagerTest, Shader) {
101 const GLuint kClient1Id = 1;
102 const GLuint kService1Id = 11;
103 const GLenum kShader1Type = GL_VERTEX_SHADER;
104 const char* kClient1Source = "hello world";
105 // Check we can create shader.
106 Shader* shader1 = manager_.CreateShader(
107 kClient1Id, kService1Id, kShader1Type);
108 // Check shader got created.
109 ASSERT_TRUE(shader1 != NULL);
110 EXPECT_EQ(kService1Id, shader1->service_id());
111 // Check if the shader has correct type.
112 EXPECT_EQ(kShader1Type, shader1->shader_type());
113 EXPECT_FALSE(shader1->IsValid());
114 EXPECT_FALSE(shader1->InUse());
115 EXPECT_TRUE(shader1->source() == NULL);
116 EXPECT_TRUE(shader1->log_info() == NULL);
117 const char* kLog = "foo";
118 shader1->SetStatus(true, kLog, NULL);
119 EXPECT_TRUE(shader1->IsValid());
120 EXPECT_STREQ(kLog, shader1->log_info()->c_str());
121 // Check we can set its source.
122 shader1->UpdateSource(kClient1Source);
123 EXPECT_STREQ(kClient1Source, shader1->source()->c_str());
124 EXPECT_EQ(NULL, shader1->translated_source());
125 // Check we can set its translated source.
126 shader1->UpdateTranslatedSource(kClient1Source);
127 EXPECT_STREQ(kClient1Source,
128 shader1->translated_source()->c_str());
131 TEST_F(ShaderManagerTest, GetInfo) {
132 const GLuint kClient1Id = 1;
133 const GLuint kService1Id = 11;
134 const GLenum kShader1Type = GL_VERTEX_SHADER;
135 const GLenum kAttrib1Type = GL_FLOAT_VEC2;
136 const GLsizei kAttrib1Size = 2;
137 const int kAttrib1Precision = SH_PRECISION_MEDIUMP;
138 const char* kAttrib1Name = "attr1";
139 const GLenum kAttrib2Type = GL_FLOAT_VEC3;
140 const GLsizei kAttrib2Size = 4;
141 const int kAttrib2Precision = SH_PRECISION_HIGHP;
142 const char* kAttrib2Name = "attr2";
143 const int kAttribStaticUse = 0;
144 const GLenum kUniform1Type = GL_FLOAT_MAT2;
145 const GLsizei kUniform1Size = 3;
146 const int kUniform1Precision = SH_PRECISION_LOWP;
147 const int kUniform1StaticUse = 1;
148 const char* kUniform1Name = "uni1";
149 const GLenum kUniform2Type = GL_FLOAT_MAT3;
150 const GLsizei kUniform2Size = 5;
151 const int kUniform2Precision = SH_PRECISION_MEDIUMP;
152 const int kUniform2StaticUse = 0;
153 const char* kUniform2Name = "uni2";
155 MockShaderTranslator shader_translator;
156 ShaderTranslator::VariableMap attrib_map;
157 attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo(
158 kAttrib1Type, kAttrib1Size, kAttrib1Precision,
159 kAttribStaticUse, kAttrib1Name);
160 attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo(
161 kAttrib2Type, kAttrib2Size, kAttrib2Precision,
162 kAttribStaticUse, kAttrib2Name);
163 ShaderTranslator::VariableMap uniform_map;
164 uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo(
165 kUniform1Type, kUniform1Size, kUniform1Precision,
166 kUniform1StaticUse, kUniform1Name);
167 uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo(
168 kUniform2Type, kUniform2Size, kUniform2Precision,
169 kUniform2StaticUse, kUniform2Name);
170 EXPECT_CALL(shader_translator, attrib_map())
171 .WillRepeatedly(ReturnRef(attrib_map));
172 EXPECT_CALL(shader_translator, uniform_map())
173 .WillRepeatedly(ReturnRef(uniform_map));
174 ShaderTranslator::VariableMap varying_map;
175 EXPECT_CALL(shader_translator, varying_map())
176 .WillRepeatedly(ReturnRef(varying_map));
177 ShaderTranslator::NameMap name_map;
178 EXPECT_CALL(shader_translator, name_map())
179 .WillRepeatedly(ReturnRef(name_map));
180 // Check we can create shader.
181 Shader* shader1 = manager_.CreateShader(
182 kClient1Id, kService1Id, kShader1Type);
183 // Check shader got created.
184 ASSERT_TRUE(shader1 != NULL);
186 shader1->SetStatus(true, "", &shader_translator);
187 // Check attrib and uniform infos got copied.
188 for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin();
189 it != attrib_map.end(); ++it) {
190 const Shader::VariableInfo* variable_info =
191 shader1->GetAttribInfo(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);
199 for (ShaderTranslator::VariableMap::const_iterator it = uniform_map.begin();
200 it != uniform_map.end(); ++it) {
201 const Shader::VariableInfo* variable_info =
202 shader1->GetUniformInfo(it->first);
203 ASSERT_TRUE(variable_info != NULL);
204 EXPECT_EQ(it->second.type, variable_info->type);
205 EXPECT_EQ(it->second.size, variable_info->size);
206 EXPECT_EQ(it->second.precision, variable_info->precision);
207 EXPECT_EQ(it->second.static_use, variable_info->static_use);
208 EXPECT_EQ(it->second.name, variable_info->name);
210 // Check attrib and uniform get cleared.
211 shader1->SetStatus(true, NULL, NULL);
212 EXPECT_TRUE(shader1->log_info() == NULL);
213 for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin();
214 it != attrib_map.end(); ++it) {
215 const Shader::VariableInfo* variable_info =
216 shader1->GetAttribInfo(it->first);
217 EXPECT_TRUE(variable_info == NULL);
219 for (ShaderTranslator::VariableMap::const_iterator it = uniform_map.begin();
220 it != uniform_map.end(); ++it) {
221 const Shader::VariableInfo* variable_info =
222 shader1->GetUniformInfo(it->first);
223 ASSERT_TRUE(variable_info == NULL);
227 TEST_F(ShaderManagerTest, ShaderInfoUseCount) {
228 const GLuint kClient1Id = 1;
229 const GLuint kService1Id = 11;
230 const GLenum kShader1Type = GL_VERTEX_SHADER;
231 // Check we can create shader.
232 Shader* shader1 = manager_.CreateShader(
233 kClient1Id, kService1Id, kShader1Type);
234 // Check shader got created.
235 ASSERT_TRUE(shader1 != NULL);
236 EXPECT_FALSE(shader1->InUse());
237 EXPECT_FALSE(shader1->IsDeleted());
238 manager_.UseShader(shader1);
239 EXPECT_TRUE(shader1->InUse());
240 manager_.UseShader(shader1);
241 EXPECT_TRUE(shader1->InUse());
242 manager_.MarkAsDeleted(shader1);
243 EXPECT_TRUE(shader1->IsDeleted());
244 Shader* shader2 = manager_.GetShader(kClient1Id);
245 EXPECT_EQ(shader1, shader2);
246 manager_.UnuseShader(shader1);
247 EXPECT_TRUE(shader1->InUse());
248 manager_.UnuseShader(shader1); // this should delete the info.
249 shader2 = manager_.GetShader(kClient1Id);
250 EXPECT_TRUE(shader2 == NULL);
252 shader1 = manager_.CreateShader(kClient1Id, kService1Id, kShader1Type);
253 ASSERT_TRUE(shader1 != NULL);
254 EXPECT_FALSE(shader1->InUse());
255 manager_.UseShader(shader1);
256 EXPECT_TRUE(shader1->InUse());
257 manager_.UseShader(shader1);
258 EXPECT_TRUE(shader1->InUse());
259 manager_.UnuseShader(shader1);
260 EXPECT_TRUE(shader1->InUse());
261 manager_.UnuseShader(shader1);
262 EXPECT_FALSE(shader1->InUse());
263 shader2 = manager_.GetShader(kClient1Id);
264 EXPECT_EQ(shader1, shader2);
265 manager_.MarkAsDeleted(shader1); // this should delete the shader.
266 shader2 = manager_.GetShader(kClient1Id);
267 EXPECT_TRUE(shader2 == NULL);