blob: 90ce0af8eff7a8ede4e866bd97d873ddb6eb0089 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#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"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000017#include "gpu/command_buffer/service/shader_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000018#include "gpu/command_buffer/service/test_helper.h"
19#include "testing/gtest/include/gtest/gtest.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000020#include "ui/gl/gl_mock.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000021
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
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000038namespace {
39void ShaderCacheCb(const std::string& key, const std::string& shader) {}
40} // namespace
41
Torne (Richard Coles)58218062012-11-14 11:43:16 +000042class ProgramManagerTest : public testing::Test {
43 public:
44 ProgramManagerTest() : manager_(NULL) { }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000045 virtual ~ProgramManagerTest() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000046 manager_.Destroy(false);
47 }
48
49 protected:
50 virtual void SetUp() {
51 gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
52 ::gfx::GLInterface::SetGLInterface(gl_.get());
53 }
54
55 virtual void TearDown() {
56 ::gfx::GLInterface::SetGLInterface(NULL);
57 gl_.reset();
58 }
59
60 // Use StrictMock to make 100% sure we know how GL will be called.
61 scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
62 ProgramManager manager_;
63};
64
65TEST_F(ProgramManagerTest, Basic) {
66 const GLuint kClient1Id = 1;
67 const GLuint kService1Id = 11;
68 const GLuint kClient2Id = 2;
69 // Check we can create program.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000070 manager_.CreateProgram(kClient1Id, kService1Id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000071 // Check program got created.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000072 Program* program1 = manager_.GetProgram(kClient1Id);
73 ASSERT_TRUE(program1 != NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000074 GLuint client_id = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000075 EXPECT_TRUE(manager_.GetClientId(program1->service_id(), &client_id));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000076 EXPECT_EQ(kClient1Id, client_id);
77 // Check we get nothing for a non-existent program.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000078 EXPECT_TRUE(manager_.GetProgram(kClient2Id) == NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000079}
80
81TEST_F(ProgramManagerTest, Destroy) {
82 const GLuint kClient1Id = 1;
83 const GLuint kService1Id = 11;
84 // Check we can create program.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000085 Program* program0 = manager_.CreateProgram(kClient1Id, kService1Id);
86 ASSERT_TRUE(program0 != NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000087 // Check program got created.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000088 Program* program1 = manager_.GetProgram(kClient1Id);
89 ASSERT_EQ(program0, program1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000090 EXPECT_CALL(*gl_, DeleteProgram(kService1Id))
91 .Times(1)
92 .RetiresOnSaturation();
93 manager_.Destroy(true);
94 // Check the resources were released.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000095 program1 = manager_.GetProgram(kClient1Id);
96 ASSERT_TRUE(program1 == NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000097}
98
99TEST_F(ProgramManagerTest, DeleteBug) {
100 ShaderManager shader_manager;
101 const GLuint kClient1Id = 1;
102 const GLuint kClient2Id = 2;
103 const GLuint kService1Id = 11;
104 const GLuint kService2Id = 12;
105 // Check we can create program.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000106 scoped_refptr<Program> program1(
107 manager_.CreateProgram(kClient1Id, kService1Id));
108 scoped_refptr<Program> program2(
109 manager_.CreateProgram(kClient2Id, kService2Id));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000110 // Check program got created.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100111 ASSERT_TRUE(program1.get());
112 ASSERT_TRUE(program2.get());
113 manager_.UseProgram(program1.get());
114 manager_.MarkAsDeleted(&shader_manager, program1.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000115 // Program will be deleted when last ref is released.
116 EXPECT_CALL(*gl_, DeleteProgram(kService2Id))
117 .Times(1)
118 .RetiresOnSaturation();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100119 manager_.MarkAsDeleted(&shader_manager, program2.get());
120 EXPECT_TRUE(manager_.IsOwned(program1.get()));
121 EXPECT_FALSE(manager_.IsOwned(program2.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000122}
123
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000124TEST_F(ProgramManagerTest, Program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000125 const GLuint kClient1Id = 1;
126 const GLuint kService1Id = 11;
127 // Check we can create program.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000128 Program* program1 = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000129 kClient1Id, kService1Id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000130 ASSERT_TRUE(program1);
131 EXPECT_EQ(kService1Id, program1->service_id());
132 EXPECT_FALSE(program1->InUse());
133 EXPECT_FALSE(program1->IsValid());
134 EXPECT_FALSE(program1->IsDeleted());
135 EXPECT_FALSE(program1->CanLink());
136 EXPECT_TRUE(program1->log_info() == NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000137}
138
139class ProgramManagerWithShaderTest : public testing::Test {
140 public:
141 ProgramManagerWithShaderTest()
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000142 : manager_(NULL), program_(NULL) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000143 }
144
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000145 virtual ~ProgramManagerWithShaderTest() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000146 manager_.Destroy(false);
147 shader_manager_.Destroy(false);
148 }
149
150 static const GLint kNumVertexAttribs = 16;
151
152 static const GLuint kClientProgramId = 123;
153 static const GLuint kServiceProgramId = 456;
154 static const GLuint kVertexShaderClientId = 201;
155 static const GLuint kFragmentShaderClientId = 202;
156 static const GLuint kVertexShaderServiceId = 301;
157 static const GLuint kFragmentShaderServiceId = 302;
158
159 static const char* kAttrib1Name;
160 static const char* kAttrib2Name;
161 static const char* kAttrib3Name;
162 static const GLint kAttrib1Size = 1;
163 static const GLint kAttrib2Size = 1;
164 static const GLint kAttrib3Size = 1;
165 static const GLint kAttrib1Location = 0;
166 static const GLint kAttrib2Location = 1;
167 static const GLint kAttrib3Location = 2;
168 static const GLenum kAttrib1Type = GL_FLOAT_VEC4;
169 static const GLenum kAttrib2Type = GL_FLOAT_VEC2;
170 static const GLenum kAttrib3Type = GL_FLOAT_VEC3;
171 static const GLint kInvalidAttribLocation = 30;
172 static const GLint kBadAttribIndex = kNumVertexAttribs;
173
174 static const char* kUniform1Name;
175 static const char* kUniform2Name;
176 static const char* kUniform3BadName;
177 static const char* kUniform3GoodName;
178 static const GLint kUniform1Size = 1;
179 static const GLint kUniform2Size = 3;
180 static const GLint kUniform3Size = 2;
181 static const GLint kUniform1FakeLocation = 0; // These are hard coded
182 static const GLint kUniform2FakeLocation = 1; // to match
183 static const GLint kUniform3FakeLocation = 2; // ProgramManager.
184 static const GLint kUniform1RealLocation = 11;
185 static const GLint kUniform2RealLocation = 22;
186 static const GLint kUniform3RealLocation = 33;
187 static const GLint kUniform1DesiredLocation = -1;
188 static const GLint kUniform2DesiredLocation = -1;
189 static const GLint kUniform3DesiredLocation = -1;
190 static const GLenum kUniform1Type = GL_FLOAT_VEC4;
191 static const GLenum kUniform2Type = GL_INT_VEC2;
192 static const GLenum kUniform3Type = GL_FLOAT_VEC3;
193 static const GLint kInvalidUniformLocation = 30;
194 static const GLint kBadUniformIndex = 1000;
195
196 static const size_t kNumAttribs;
197 static const size_t kNumUniforms;
198
199 protected:
200 typedef TestHelper::AttribInfo AttribInfo;
201 typedef TestHelper::UniformInfo UniformInfo;
202
203 virtual void SetUp() {
204 gl_.reset(new StrictMock<gfx::MockGLInterface>());
205 ::gfx::GLInterface::SetGLInterface(gl_.get());
206
207 SetupDefaultShaderExpectations();
208
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000209 Shader* vertex_shader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000210 kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000211 Shader* fragment_shader =
212 shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000213 kFragmentShaderClientId, kFragmentShaderServiceId,
214 GL_FRAGMENT_SHADER);
215 ASSERT_TRUE(vertex_shader != NULL);
216 ASSERT_TRUE(fragment_shader != NULL);
217 vertex_shader->SetStatus(true, NULL, NULL);
218 fragment_shader->SetStatus(true, NULL, NULL);
219
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000220 program_ = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000221 kClientProgramId, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000222 ASSERT_TRUE(program_ != NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000223
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000224 program_->AttachShader(&shader_manager_, vertex_shader);
225 program_->AttachShader(&shader_manager_, fragment_shader);
226 program_->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000227 }
228
229 void SetupShader(AttribInfo* attribs, size_t num_attribs,
230 UniformInfo* uniforms, size_t num_uniforms,
231 GLuint service_id) {
232 TestHelper::SetupShader(
233 gl_.get(), attribs, num_attribs, uniforms, num_uniforms, service_id);
234 }
235
236 void SetupDefaultShaderExpectations() {
237 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
238 kServiceProgramId);
239 }
240
241 void SetupExpectationsForClearingUniforms(
242 UniformInfo* uniforms, size_t num_uniforms) {
243 TestHelper::SetupExpectationsForClearingUniforms(
244 gl_.get(), uniforms, num_uniforms);
245 }
246
247 virtual void TearDown() {
248 ::gfx::GLInterface::SetGLInterface(NULL);
249 }
250
251 // Return true if link status matches expected_link_status
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000252 bool LinkAsExpected(Program* program,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000253 bool expected_link_status) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000254 GLuint service_id = program->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000255 if (expected_link_status) {
256 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
257 service_id);
258 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000259 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000260 GLint link_status;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000261 program->GetProgramiv(GL_LINK_STATUS, &link_status);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000262 return (static_cast<bool>(link_status) == expected_link_status);
263 }
264
265 static AttribInfo kAttribs[];
266 static UniformInfo kUniforms[];
267
268 scoped_ptr<StrictMock<gfx::MockGLInterface> > gl_;
269
270 ProgramManager manager_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000271 Program* program_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000272 ShaderManager shader_manager_;
273};
274
275ProgramManagerWithShaderTest::AttribInfo
276 ProgramManagerWithShaderTest::kAttribs[] = {
277 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
278 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, },
279 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
280};
281
282// GCC requires these declarations, but MSVC requires they not be present
283#ifndef COMPILER_MSVC
284const GLint ProgramManagerWithShaderTest::kNumVertexAttribs;
285const GLuint ProgramManagerWithShaderTest::kClientProgramId;
286const GLuint ProgramManagerWithShaderTest::kServiceProgramId;
287const GLuint ProgramManagerWithShaderTest::kVertexShaderClientId;
288const GLuint ProgramManagerWithShaderTest::kFragmentShaderClientId;
289const GLuint ProgramManagerWithShaderTest::kVertexShaderServiceId;
290const GLuint ProgramManagerWithShaderTest::kFragmentShaderServiceId;
291const GLint ProgramManagerWithShaderTest::kAttrib1Size;
292const GLint ProgramManagerWithShaderTest::kAttrib2Size;
293const GLint ProgramManagerWithShaderTest::kAttrib3Size;
294const GLint ProgramManagerWithShaderTest::kAttrib1Location;
295const GLint ProgramManagerWithShaderTest::kAttrib2Location;
296const GLint ProgramManagerWithShaderTest::kAttrib3Location;
297const GLenum ProgramManagerWithShaderTest::kAttrib1Type;
298const GLenum ProgramManagerWithShaderTest::kAttrib2Type;
299const GLenum ProgramManagerWithShaderTest::kAttrib3Type;
300const GLint ProgramManagerWithShaderTest::kInvalidAttribLocation;
301const GLint ProgramManagerWithShaderTest::kBadAttribIndex;
302const GLint ProgramManagerWithShaderTest::kUniform1Size;
303const GLint ProgramManagerWithShaderTest::kUniform2Size;
304const GLint ProgramManagerWithShaderTest::kUniform3Size;
305const GLint ProgramManagerWithShaderTest::kUniform1FakeLocation;
306const GLint ProgramManagerWithShaderTest::kUniform2FakeLocation;
307const GLint ProgramManagerWithShaderTest::kUniform3FakeLocation;
308const GLint ProgramManagerWithShaderTest::kUniform1RealLocation;
309const GLint ProgramManagerWithShaderTest::kUniform2RealLocation;
310const GLint ProgramManagerWithShaderTest::kUniform3RealLocation;
311const GLint ProgramManagerWithShaderTest::kUniform1DesiredLocation;
312const GLint ProgramManagerWithShaderTest::kUniform2DesiredLocation;
313const GLint ProgramManagerWithShaderTest::kUniform3DesiredLocation;
314const GLenum ProgramManagerWithShaderTest::kUniform1Type;
315const GLenum ProgramManagerWithShaderTest::kUniform2Type;
316const GLenum ProgramManagerWithShaderTest::kUniform3Type;
317const GLint ProgramManagerWithShaderTest::kInvalidUniformLocation;
318const GLint ProgramManagerWithShaderTest::kBadUniformIndex;
319#endif
320
321const size_t ProgramManagerWithShaderTest::kNumAttribs =
322 arraysize(ProgramManagerWithShaderTest::kAttribs);
323
324ProgramManagerWithShaderTest::UniformInfo
325 ProgramManagerWithShaderTest::kUniforms[] = {
326 { kUniform1Name,
327 kUniform1Size,
328 kUniform1Type,
329 kUniform1FakeLocation,
330 kUniform1RealLocation,
331 kUniform1DesiredLocation,
332 kUniform1Name,
333 },
334 { kUniform2Name,
335 kUniform2Size,
336 kUniform2Type,
337 kUniform2FakeLocation,
338 kUniform2RealLocation,
339 kUniform2DesiredLocation,
340 kUniform2Name,
341 },
342 { kUniform3BadName,
343 kUniform3Size,
344 kUniform3Type,
345 kUniform3FakeLocation,
346 kUniform3RealLocation,
347 kUniform3DesiredLocation,
348 kUniform3GoodName,
349 },
350};
351
352const size_t ProgramManagerWithShaderTest::kNumUniforms =
353 arraysize(ProgramManagerWithShaderTest::kUniforms);
354
355const char* ProgramManagerWithShaderTest::kAttrib1Name = "attrib1";
356const char* ProgramManagerWithShaderTest::kAttrib2Name = "attrib2";
357const char* ProgramManagerWithShaderTest::kAttrib3Name = "attrib3";
358const char* ProgramManagerWithShaderTest::kUniform1Name = "uniform1";
359// Correctly has array spec.
360const char* ProgramManagerWithShaderTest::kUniform2Name = "uniform2[0]";
361// Incorrectly missing array spec.
362const char* ProgramManagerWithShaderTest::kUniform3BadName = "uniform3";
363const char* ProgramManagerWithShaderTest::kUniform3GoodName = "uniform3[0]";
364
365TEST_F(ProgramManagerWithShaderTest, GetAttribInfos) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000366 const Program* program = manager_.GetProgram(kClientProgramId);
367 ASSERT_TRUE(program != NULL);
368 const Program::AttribInfoVector& infos =
369 program->GetAttribInfos();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000370 ASSERT_EQ(kNumAttribs, infos.size());
371 for (size_t ii = 0; ii < kNumAttribs; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000372 const Program::VertexAttrib& info = infos[ii];
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000373 const AttribInfo& expected = kAttribs[ii];
374 EXPECT_EQ(expected.size, info.size);
375 EXPECT_EQ(expected.type, info.type);
376 EXPECT_EQ(expected.location, info.location);
377 EXPECT_STREQ(expected.name, info.name.c_str());
378 }
379}
380
381TEST_F(ProgramManagerWithShaderTest, GetAttribInfo) {
382 const GLint kValidIndex = 1;
383 const GLint kInvalidIndex = 1000;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000384 const Program* program = manager_.GetProgram(kClientProgramId);
385 ASSERT_TRUE(program != NULL);
386 const Program::VertexAttrib* info =
387 program->GetAttribInfo(kValidIndex);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000388 ASSERT_TRUE(info != NULL);
389 EXPECT_EQ(kAttrib2Size, info->size);
390 EXPECT_EQ(kAttrib2Type, info->type);
391 EXPECT_EQ(kAttrib2Location, info->location);
392 EXPECT_STREQ(kAttrib2Name, info->name.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000393 EXPECT_TRUE(program->GetAttribInfo(kInvalidIndex) == NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000394}
395
396TEST_F(ProgramManagerWithShaderTest, GetAttribLocation) {
397 const char* kInvalidName = "foo";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000398 const Program* program = manager_.GetProgram(kClientProgramId);
399 ASSERT_TRUE(program != NULL);
400 EXPECT_EQ(kAttrib2Location, program->GetAttribLocation(kAttrib2Name));
401 EXPECT_EQ(-1, program->GetAttribLocation(kInvalidName));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000402}
403
404TEST_F(ProgramManagerWithShaderTest, GetUniformInfo) {
405 const GLint kInvalidIndex = 1000;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000406 const Program* program = manager_.GetProgram(kClientProgramId);
407 ASSERT_TRUE(program != NULL);
408 const Program::UniformInfo* info =
409 program->GetUniformInfo(0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000410 ASSERT_TRUE(info != NULL);
411 EXPECT_EQ(kUniform1Size, info->size);
412 EXPECT_EQ(kUniform1Type, info->type);
413 EXPECT_EQ(kUniform1RealLocation, info->element_locations[0]);
414 EXPECT_STREQ(kUniform1Name, info->name.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000415 info = program->GetUniformInfo(1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000416 ASSERT_TRUE(info != NULL);
417 EXPECT_EQ(kUniform2Size, info->size);
418 EXPECT_EQ(kUniform2Type, info->type);
419 EXPECT_EQ(kUniform2RealLocation, info->element_locations[0]);
420 EXPECT_STREQ(kUniform2Name, info->name.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000421 info = program->GetUniformInfo(2);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000422 // We emulate certain OpenGL drivers by supplying the name without
423 // the array spec. Our implementation should correctly add the required spec.
424 ASSERT_TRUE(info != NULL);
425 EXPECT_EQ(kUniform3Size, info->size);
426 EXPECT_EQ(kUniform3Type, info->type);
427 EXPECT_EQ(kUniform3RealLocation, info->element_locations[0]);
428 EXPECT_STREQ(kUniform3GoodName, info->name.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000429 EXPECT_TRUE(program->GetUniformInfo(kInvalidIndex) == NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000430}
431
432TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) {
433 static const GLuint kClientProgramId = 124;
434 static const GLuint kServiceProgramId = 457;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000435 Program* program = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000436 kClientProgramId, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000437 ASSERT_TRUE(program != NULL);
438 EXPECT_FALSE(program->CanLink());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000439 const GLuint kVShaderClientId = 2001;
440 const GLuint kFShaderClientId = 2002;
441 const GLuint kVShaderServiceId = 3001;
442 const GLuint kFShaderServiceId = 3002;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000443 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000444 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
445 ASSERT_TRUE(vshader != NULL);
446 vshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000447 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000448 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
449 ASSERT_TRUE(fshader != NULL);
450 fshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000451 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
452 EXPECT_FALSE(program->CanLink());
453 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
454 EXPECT_TRUE(program->CanLink());
455 program->DetachShader(&shader_manager_, vshader);
456 EXPECT_FALSE(program->CanLink());
457 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
458 EXPECT_TRUE(program->CanLink());
459 program->DetachShader(&shader_manager_, fshader);
460 EXPECT_FALSE(program->CanLink());
461 EXPECT_FALSE(program->AttachShader(&shader_manager_, vshader));
462 EXPECT_FALSE(program->CanLink());
463 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
464 EXPECT_TRUE(program->CanLink());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000465 vshader->SetStatus(false, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000466 EXPECT_FALSE(program->CanLink());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000467 vshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000468 EXPECT_TRUE(program->CanLink());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000469 fshader->SetStatus(false, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000470 EXPECT_FALSE(program->CanLink());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000471 fshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000472 EXPECT_TRUE(program->CanLink());
473 EXPECT_TRUE(program->DetachShader(&shader_manager_, fshader));
474 EXPECT_FALSE(program->DetachShader(&shader_manager_, fshader));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000475}
476
477TEST_F(ProgramManagerWithShaderTest, GetUniformFakeLocation) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000478 const Program* program = manager_.GetProgram(kClientProgramId);
479 ASSERT_TRUE(program != NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000480 EXPECT_EQ(kUniform1FakeLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000481 program->GetUniformFakeLocation(kUniform1Name));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000482 EXPECT_EQ(kUniform2FakeLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000483 program->GetUniformFakeLocation(kUniform2Name));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000484 EXPECT_EQ(kUniform3FakeLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000485 program->GetUniformFakeLocation(kUniform3BadName));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000486 // Check we can get uniform2 as "uniform2" even though the name is
487 // "uniform2[0]"
488 EXPECT_EQ(kUniform2FakeLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000489 program->GetUniformFakeLocation("uniform2"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000490 // Check we can get uniform3 as "uniform3[0]" even though we simulated GL
491 // returning "uniform3"
492 EXPECT_EQ(kUniform3FakeLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000493 program->GetUniformFakeLocation(kUniform3GoodName));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000494 // Check that we can get the locations of the array elements > 1
495 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation, 1),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000496 program->GetUniformFakeLocation("uniform2[1]"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000497 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation, 2),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000498 program->GetUniformFakeLocation("uniform2[2]"));
499 EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform2[3]"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000500 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform3FakeLocation, 1),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000501 program->GetUniformFakeLocation("uniform3[1]"));
502 EXPECT_EQ(-1, program->GetUniformFakeLocation("uniform3[2]"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000503}
504
505TEST_F(ProgramManagerWithShaderTest, GetUniformInfoByFakeLocation) {
506 const GLint kInvalidLocation = 1234;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000507 const Program::UniformInfo* info;
508 const Program* program = manager_.GetProgram(kClientProgramId);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000509 GLint real_location = -1;
510 GLint array_index = -1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000511 ASSERT_TRUE(program != NULL);
512 info = program->GetUniformInfoByFakeLocation(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000513 kUniform2FakeLocation, &real_location, &array_index);
514 EXPECT_EQ(kUniform2RealLocation, real_location);
515 EXPECT_EQ(0, array_index);
516 ASSERT_TRUE(info != NULL);
517 EXPECT_EQ(kUniform2Type, info->type);
518 real_location = -1;
519 array_index = -1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000520 info = program->GetUniformInfoByFakeLocation(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000521 kInvalidLocation, &real_location, &array_index);
522 EXPECT_TRUE(info == NULL);
523 EXPECT_EQ(-1, real_location);
524 EXPECT_EQ(-1, array_index);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000525 GLint loc = program->GetUniformFakeLocation("uniform2[2]");
526 info = program->GetUniformInfoByFakeLocation(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000527 loc, &real_location, &array_index);
528 ASSERT_TRUE(info != NULL);
529 EXPECT_EQ(kUniform2RealLocation + 2 * 2, real_location);
530 EXPECT_EQ(2, array_index);
531}
532
533// Some GL drivers incorrectly return gl_DepthRange and possibly other uniforms
534// that start with "gl_". Our implementation catches these and does not allow
535// them back to client.
536TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) {
537 static const char* kUniform2Name = "gl_longNameWeCanCheckFor";
538 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
539 { kUniform1Name,
540 kUniform1Size,
541 kUniform1Type,
542 kUniform1FakeLocation,
543 kUniform1RealLocation,
544 kUniform1DesiredLocation,
545 kUniform1Name,
546 },
547 { kUniform2Name,
548 kUniform2Size,
549 kUniform2Type,
550 kUniform2FakeLocation,
551 kUniform2RealLocation,
552 kUniform2DesiredLocation,
553 kUniform2Name,
554 },
555 { kUniform3BadName,
556 kUniform3Size,
557 kUniform3Type,
558 kUniform3FakeLocation,
559 kUniform3RealLocation,
560 kUniform3DesiredLocation,
561 kUniform3GoodName,
562 },
563 };
564 const size_t kNumUniforms = arraysize(kUniforms);
565 static const GLuint kClientProgramId = 1234;
566 static const GLuint kServiceProgramId = 5679;
567 const GLuint kVShaderClientId = 2001;
568 const GLuint kFShaderClientId = 2002;
569 const GLuint kVShaderServiceId = 3001;
570 const GLuint kFShaderServiceId = 3002;
571 SetupShader(
572 kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000573 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000574 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
575 ASSERT_TRUE(vshader != NULL);
576 vshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000577 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000578 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
579 ASSERT_TRUE(fshader != NULL);
580 fshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000581 Program* program =
582 manager_.CreateProgram(kClientProgramId, kServiceProgramId);
583 ASSERT_TRUE(program != NULL);
584 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
585 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
586 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000587 GLint value = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000588 program->GetProgramiv(GL_ACTIVE_ATTRIBUTES, &value);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000589 EXPECT_EQ(3, value);
590 // Check that we skipped the "gl_" uniform.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000591 program->GetProgramiv(GL_ACTIVE_UNIFORMS, &value);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000592 EXPECT_EQ(2, value);
593 // Check that our max length adds room for the array spec and is not as long
594 // as the "gl_" uniform we skipped.
595 // +4u is to account for "gl_" and NULL terminator.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000596 program->GetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH, &value);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000597 EXPECT_EQ(strlen(kUniform3BadName) + 4u, static_cast<size_t>(value));
598}
599
600// Test the bug comparing similar array names is fixed.
601TEST_F(ProgramManagerWithShaderTest, SimilarArrayNames) {
602 static const char* kUniform2Name = "u_nameLong[0]";
603 static const char* kUniform3Name = "u_name[0]";
604 static const GLint kUniform2Size = 2;
605 static const GLint kUniform3Size = 2;
606 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
607 { kUniform1Name,
608 kUniform1Size,
609 kUniform1Type,
610 kUniform1FakeLocation,
611 kUniform1RealLocation,
612 kUniform1DesiredLocation,
613 kUniform1Name,
614 },
615 { kUniform2Name,
616 kUniform2Size,
617 kUniform2Type,
618 kUniform2FakeLocation,
619 kUniform2RealLocation,
620 kUniform2DesiredLocation,
621 kUniform2Name,
622 },
623 { kUniform3Name,
624 kUniform3Size,
625 kUniform3Type,
626 kUniform3FakeLocation,
627 kUniform3RealLocation,
628 kUniform3DesiredLocation,
629 kUniform3Name,
630 },
631 };
632 const size_t kNumUniforms = arraysize(kUniforms);
633 static const GLuint kClientProgramId = 1234;
634 static const GLuint kServiceProgramId = 5679;
635 const GLuint kVShaderClientId = 2001;
636 const GLuint kFShaderClientId = 2002;
637 const GLuint kVShaderServiceId = 3001;
638 const GLuint kFShaderServiceId = 3002;
639 SetupShader(
640 kAttribs, kNumAttribs, kUniforms, kNumUniforms, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000641 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000642 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
643 ASSERT_TRUE(vshader != NULL);
644 vshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000645 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000646 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
647 ASSERT_TRUE(fshader != NULL);
648 fshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000649 Program* program =
650 manager_.CreateProgram(kClientProgramId, kServiceProgramId);
651 ASSERT_TRUE(program != NULL);
652 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
653 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
654 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000655
656 // Check that we get the correct locations.
657 EXPECT_EQ(kUniform2FakeLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000658 program->GetUniformFakeLocation(kUniform2Name));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000659 EXPECT_EQ(kUniform3FakeLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000660 program->GetUniformFakeLocation(kUniform3Name));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000661}
662
663// Some GL drivers incorrectly return the wrong type. For example they return
664// GL_FLOAT_VEC2 when they should return GL_FLOAT_MAT2. Check we handle this.
665TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) {
666 static GLenum kAttrib2BadType = GL_FLOAT_VEC2;
667 static GLenum kAttrib2GoodType = GL_FLOAT_MAT2;
668 static GLenum kUniform2BadType = GL_FLOAT_VEC3;
669 static GLenum kUniform2GoodType = GL_FLOAT_MAT3;
670 MockShaderTranslator shader_translator;
671 ShaderTranslator::VariableMap attrib_map;
672 ShaderTranslator::VariableMap uniform_map;
673 attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo(
674 kAttrib1Type, kAttrib1Size, kAttrib1Name);
675 attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo(
676 kAttrib2GoodType, kAttrib2Size, kAttrib2Name);
677 attrib_map[kAttrib3Name] = ShaderTranslatorInterface::VariableInfo(
678 kAttrib3Type, kAttrib3Size, kAttrib3Name);
679 uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo(
680 kUniform1Type, kUniform1Size, kUniform1Name);
681 uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo(
682 kUniform2GoodType, kUniform2Size, kUniform2Name);
683 uniform_map[kUniform3GoodName] = ShaderTranslatorInterface::VariableInfo(
684 kUniform3Type, kUniform3Size, kUniform3GoodName);
685 EXPECT_CALL(shader_translator, attrib_map())
686 .WillRepeatedly(ReturnRef(attrib_map));
687 EXPECT_CALL(shader_translator, uniform_map())
688 .WillRepeatedly(ReturnRef(uniform_map));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000689 ShaderTranslator::NameMap name_map;
690 EXPECT_CALL(shader_translator, name_map())
691 .WillRepeatedly(ReturnRef(name_map));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000692 const GLuint kVShaderClientId = 2001;
693 const GLuint kFShaderClientId = 2002;
694 const GLuint kVShaderServiceId = 3001;
695 const GLuint kFShaderServiceId = 3002;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000696 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000697 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
698 ASSERT_TRUE(vshader != NULL);
699 vshader->SetStatus(true, "", &shader_translator);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000700 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000701 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
702 ASSERT_TRUE(fshader != NULL);
703 fshader->SetStatus(true, "", &shader_translator);
704 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = {
705 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
706 { kAttrib2Name, kAttrib2Size, kAttrib2BadType, kAttrib2Location, },
707 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
708 };
709 static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
710 { kUniform1Name,
711 kUniform1Size,
712 kUniform1Type,
713 kUniform1FakeLocation,
714 kUniform1RealLocation,
715 kUniform1DesiredLocation,
716 kUniform1Name,
717 },
718 { kUniform2Name,
719 kUniform2Size,
720 kUniform2BadType,
721 kUniform2FakeLocation,
722 kUniform2RealLocation,
723 kUniform2DesiredLocation,
724 kUniform2Name,
725 },
726 { kUniform3BadName,
727 kUniform3Size,
728 kUniform3Type,
729 kUniform3FakeLocation,
730 kUniform3RealLocation,
731 kUniform3DesiredLocation,
732 kUniform3GoodName,
733 },
734 };
735 const size_t kNumAttribs= arraysize(kAttribs);
736 const size_t kNumUniforms = arraysize(kUniforms);
737 static const GLuint kClientProgramId = 1234;
738 static const GLuint kServiceProgramId = 5679;
739 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
740 kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000741 Program* program = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000742 kClientProgramId, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000743 ASSERT_TRUE(program!= NULL);
744 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
745 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
746 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000747 // Check that we got the good type, not the bad.
748 // Check Attribs
749 for (unsigned index = 0; index < kNumAttribs; ++index) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000750 const Program::VertexAttrib* attrib_info =
751 program->GetAttribInfo(index);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000752 ASSERT_TRUE(attrib_info != NULL);
753 ShaderTranslator::VariableMap::const_iterator it = attrib_map.find(
754 attrib_info->name);
755 ASSERT_TRUE(it != attrib_map.end());
756 EXPECT_EQ(it->first, attrib_info->name);
757 EXPECT_EQ(static_cast<GLenum>(it->second.type), attrib_info->type);
758 EXPECT_EQ(it->second.size, attrib_info->size);
759 EXPECT_EQ(it->second.name, attrib_info->name);
760 }
761 // Check Uniforms
762 for (unsigned index = 0; index < kNumUniforms; ++index) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000763 const Program::UniformInfo* uniform_info =
764 program->GetUniformInfo(index);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000765 ASSERT_TRUE(uniform_info != NULL);
766 ShaderTranslator::VariableMap::const_iterator it = uniform_map.find(
767 uniform_info->name);
768 ASSERT_TRUE(it != uniform_map.end());
769 EXPECT_EQ(it->first, uniform_info->name);
770 EXPECT_EQ(static_cast<GLenum>(it->second.type), uniform_info->type);
771 EXPECT_EQ(it->second.size, uniform_info->size);
772 EXPECT_EQ(it->second.name, uniform_info->name);
773 }
774}
775
776TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount) {
777 static const GLuint kClientProgramId = 124;
778 static const GLuint kServiceProgramId = 457;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000779 Program* program = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000780 kClientProgramId, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000781 ASSERT_TRUE(program != NULL);
782 EXPECT_FALSE(program->CanLink());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000783 const GLuint kVShaderClientId = 2001;
784 const GLuint kFShaderClientId = 2002;
785 const GLuint kVShaderServiceId = 3001;
786 const GLuint kFShaderServiceId = 3002;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000787 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000788 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
789 ASSERT_TRUE(vshader != NULL);
790 vshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000791 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000792 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
793 ASSERT_TRUE(fshader != NULL);
794 fshader->SetStatus(true, "", NULL);
795 EXPECT_FALSE(vshader->InUse());
796 EXPECT_FALSE(fshader->InUse());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000797 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000798 EXPECT_TRUE(vshader->InUse());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000799 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000800 EXPECT_TRUE(fshader->InUse());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000801 EXPECT_TRUE(program->CanLink());
802 EXPECT_FALSE(program->InUse());
803 EXPECT_FALSE(program->IsDeleted());
804 manager_.UseProgram(program);
805 EXPECT_TRUE(program->InUse());
806 manager_.UseProgram(program);
807 EXPECT_TRUE(program->InUse());
808 manager_.MarkAsDeleted(&shader_manager_, program);
809 EXPECT_TRUE(program->IsDeleted());
810 Program* info2 = manager_.GetProgram(kClientProgramId);
811 EXPECT_EQ(program, info2);
812 manager_.UnuseProgram(&shader_manager_, program);
813 EXPECT_TRUE(program->InUse());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000814 // this should delete the info.
815 EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId))
816 .Times(1)
817 .RetiresOnSaturation();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000818 manager_.UnuseProgram(&shader_manager_, program);
819 info2 = manager_.GetProgram(kClientProgramId);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000820 EXPECT_TRUE(info2 == NULL);
821 EXPECT_FALSE(vshader->InUse());
822 EXPECT_FALSE(fshader->InUse());
823}
824
825TEST_F(ProgramManagerWithShaderTest, ProgramInfoUseCount2) {
826 static const GLuint kClientProgramId = 124;
827 static const GLuint kServiceProgramId = 457;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000828 Program* program = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000829 kClientProgramId, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000830 ASSERT_TRUE(program != NULL);
831 EXPECT_FALSE(program->CanLink());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000832 const GLuint kVShaderClientId = 2001;
833 const GLuint kFShaderClientId = 2002;
834 const GLuint kVShaderServiceId = 3001;
835 const GLuint kFShaderServiceId = 3002;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000836 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000837 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
838 ASSERT_TRUE(vshader != NULL);
839 vshader->SetStatus(true, "", NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000840 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000841 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
842 ASSERT_TRUE(fshader != NULL);
843 fshader->SetStatus(true, "", NULL);
844 EXPECT_FALSE(vshader->InUse());
845 EXPECT_FALSE(fshader->InUse());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000846 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000847 EXPECT_TRUE(vshader->InUse());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000848 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000849 EXPECT_TRUE(fshader->InUse());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000850 EXPECT_TRUE(program->CanLink());
851 EXPECT_FALSE(program->InUse());
852 EXPECT_FALSE(program->IsDeleted());
853 manager_.UseProgram(program);
854 EXPECT_TRUE(program->InUse());
855 manager_.UseProgram(program);
856 EXPECT_TRUE(program->InUse());
857 manager_.UnuseProgram(&shader_manager_, program);
858 EXPECT_TRUE(program->InUse());
859 manager_.UnuseProgram(&shader_manager_, program);
860 EXPECT_FALSE(program->InUse());
861 Program* info2 = manager_.GetProgram(kClientProgramId);
862 EXPECT_EQ(program, info2);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000863 // this should delete the program.
864 EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId))
865 .Times(1)
866 .RetiresOnSaturation();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000867 manager_.MarkAsDeleted(&shader_manager_, program);
868 info2 = manager_.GetProgram(kClientProgramId);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000869 EXPECT_TRUE(info2 == NULL);
870 EXPECT_FALSE(vshader->InUse());
871 EXPECT_FALSE(fshader->InUse());
872}
873
874TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetProgramInfo) {
875 CommonDecoder::Bucket bucket;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000876 const Program* program = manager_.GetProgram(kClientProgramId);
877 ASSERT_TRUE(program != NULL);
878 program->GetProgramInfo(&manager_, &bucket);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000879 ProgramInfoHeader* header =
880 bucket.GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader));
881 ASSERT_TRUE(header != NULL);
882 EXPECT_EQ(1u, header->link_status);
883 EXPECT_EQ(arraysize(kAttribs), header->num_attribs);
884 EXPECT_EQ(arraysize(kUniforms), header->num_uniforms);
885 const ProgramInput* inputs = bucket.GetDataAs<const ProgramInput*>(
886 sizeof(*header),
887 sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
888 ASSERT_TRUE(inputs != NULL);
889 const ProgramInput* input = inputs;
890 // TODO(gman): Don't assume these are in order.
891 for (uint32 ii = 0; ii < header->num_attribs; ++ii) {
892 const AttribInfo& expected = kAttribs[ii];
893 EXPECT_EQ(expected.size, input->size);
894 EXPECT_EQ(expected.type, input->type);
895 const int32* location = bucket.GetDataAs<const int32*>(
896 input->location_offset, sizeof(int32));
897 ASSERT_TRUE(location != NULL);
898 EXPECT_EQ(expected.location, *location);
899 const char* name_buf = bucket.GetDataAs<const char*>(
900 input->name_offset, input->name_length);
901 ASSERT_TRUE(name_buf != NULL);
902 std::string name(name_buf, input->name_length);
903 EXPECT_STREQ(expected.name, name.c_str());
904 ++input;
905 }
906 // TODO(gman): Don't assume these are in order.
907 for (uint32 ii = 0; ii < header->num_uniforms; ++ii) {
908 const UniformInfo& expected = kUniforms[ii];
909 EXPECT_EQ(expected.size, input->size);
910 EXPECT_EQ(expected.type, input->type);
911 const int32* locations = bucket.GetDataAs<const int32*>(
912 input->location_offset, sizeof(int32) * input->size);
913 ASSERT_TRUE(locations != NULL);
914 for (int32 jj = 0; jj < input->size; ++jj) {
915 EXPECT_EQ(
916 ProgramManager::MakeFakeLocation(expected.fake_location, jj),
917 locations[jj]);
918 }
919 const char* name_buf = bucket.GetDataAs<const char*>(
920 input->name_offset, input->name_length);
921 ASSERT_TRUE(name_buf != NULL);
922 std::string name(name_buf, input->name_length);
923 EXPECT_STREQ(expected.good_name, name.c_str());
924 ++input;
925 }
926 EXPECT_EQ(header->num_attribs + header->num_uniforms,
927 static_cast<uint32>(input - inputs));
928}
929
930TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) {
931 // Set up shader
932 const GLuint kVShaderClientId = 1;
933 const GLuint kVShaderServiceId = 11;
934 const GLuint kFShaderClientId = 2;
935 const GLuint kFShaderServiceId = 12;
936 MockShaderTranslator shader_translator;
937 ShaderTranslator::VariableMap attrib_map;
938 for (uint32 ii = 0; ii < kNumAttribs; ++ii) {
939 attrib_map[kAttribs[ii].name] = ShaderTranslatorInterface::VariableInfo(
940 kAttribs[ii].type, kAttribs[ii].size, kAttribs[ii].name);
941 }
942 ShaderTranslator::VariableMap uniform_map;
943 EXPECT_CALL(shader_translator, attrib_map())
944 .WillRepeatedly(ReturnRef(attrib_map));
945 EXPECT_CALL(shader_translator, uniform_map())
946 .WillRepeatedly(ReturnRef(uniform_map));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000947 ShaderTranslator::NameMap name_map;
948 EXPECT_CALL(shader_translator, name_map())
949 .WillRepeatedly(ReturnRef(name_map));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000950 // Check we can create shader.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000951 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000952 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000953 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000954 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
955 // Check shader got created.
956 ASSERT_TRUE(vshader != NULL && fshader != NULL);
957 // Set Status
958 vshader->SetStatus(true, "", &shader_translator);
959 // Check attrib infos got copied.
960 for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin();
961 it != attrib_map.end(); ++it) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000962 const Shader::VariableInfo* variable_info =
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000963 vshader->GetAttribInfo(it->first);
964 ASSERT_TRUE(variable_info != NULL);
965 EXPECT_EQ(it->second.type, variable_info->type);
966 EXPECT_EQ(it->second.size, variable_info->size);
967 EXPECT_EQ(it->second.name, variable_info->name);
968 }
969 fshader->SetStatus(true, "", NULL);
970
971 // Set up program
972 const GLuint kClientProgramId = 6666;
973 const GLuint kServiceProgramId = 8888;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000974 Program* program =
975 manager_.CreateProgram(kClientProgramId, kServiceProgramId);
976 ASSERT_TRUE(program != NULL);
977 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
978 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000979
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000980 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts());
981 EXPECT_TRUE(LinkAsExpected(program, true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000982
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000983 program->SetAttribLocationBinding(kAttrib1Name, 0);
984 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts());
985 EXPECT_TRUE(LinkAsExpected(program, true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000986
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000987 program->SetAttribLocationBinding("xxx", 0);
988 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts());
989 EXPECT_TRUE(LinkAsExpected(program, true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000990
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000991 program->SetAttribLocationBinding(kAttrib2Name, 1);
992 EXPECT_FALSE(program->DetectAttribLocationBindingConflicts());
993 EXPECT_TRUE(LinkAsExpected(program, true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000994
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000995 program->SetAttribLocationBinding(kAttrib2Name, 0);
996 EXPECT_TRUE(program->DetectAttribLocationBindingConflicts());
997 EXPECT_TRUE(LinkAsExpected(program, false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000998}
999
1000TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) {
1001 const GLuint kVShaderClientId = 2001;
1002 const GLuint kFShaderClientId = 2002;
1003 const GLuint kVShaderServiceId = 3001;
1004 const GLuint kFShaderServiceId = 3002;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001005 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001006 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
1007 ASSERT_TRUE(vshader != NULL);
1008 vshader->SetStatus(true, NULL, NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001009 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001010 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
1011 ASSERT_TRUE(fshader != NULL);
1012 fshader->SetStatus(true, NULL, NULL);
1013 static const GLuint kClientProgramId = 1234;
1014 static const GLuint kServiceProgramId = 5679;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001015 Program* program = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001016 kClientProgramId, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001017 ASSERT_TRUE(program != NULL);
1018 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
1019 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001020
1021 static const GLenum kSamplerTypes[] = {
1022 GL_SAMPLER_2D,
1023 GL_SAMPLER_CUBE,
1024 GL_SAMPLER_EXTERNAL_OES,
1025 GL_SAMPLER_3D_OES,
1026 GL_SAMPLER_2D_RECT_ARB,
1027 };
1028 const size_t kNumSamplerTypes = arraysize(kSamplerTypes);
1029 for (size_t ii = 0; ii < kNumSamplerTypes; ++ii) {
1030 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = {
1031 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
1032 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, },
1033 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
1034 };
1035 ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
1036 { kUniform1Name,
1037 kUniform1Size,
1038 kUniform1Type,
1039 kUniform1FakeLocation,
1040 kUniform1RealLocation,
1041 kUniform1DesiredLocation,
1042 kUniform1Name,
1043 },
1044 { kUniform2Name,
1045 kUniform2Size,
1046 kSamplerTypes[ii],
1047 kUniform2FakeLocation,
1048 kUniform2RealLocation,
1049 kUniform2DesiredLocation,
1050 kUniform2Name,
1051 },
1052 { kUniform3BadName,
1053 kUniform3Size,
1054 kUniform3Type,
1055 kUniform3FakeLocation,
1056 kUniform3RealLocation,
1057 kUniform3DesiredLocation,
1058 kUniform3GoodName,
1059 },
1060 };
1061 const size_t kNumAttribs = arraysize(kAttribs);
1062 const size_t kNumUniforms = arraysize(kUniforms);
1063 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
1064 kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001065 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001066 SetupExpectationsForClearingUniforms(kUniforms, kNumUniforms);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001067 manager_.ClearUniforms(program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001068 }
1069}
1070
1071TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) {
1072 const GLuint kVShaderClientId = 2001;
1073 const GLuint kFShaderClientId = 2002;
1074 const GLuint kVShaderServiceId = 3001;
1075 const GLuint kFShaderServiceId = 3002;
1076
1077 const GLint kUniform1DesiredLocation = 10;
1078 const GLint kUniform2DesiredLocation = -1;
1079 const GLint kUniform3DesiredLocation = 5;
1080
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001081 Shader* vshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001082 kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
1083 ASSERT_TRUE(vshader != NULL);
1084 vshader->SetStatus(true, NULL, NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001085 Shader* fshader = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001086 kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
1087 ASSERT_TRUE(fshader != NULL);
1088 fshader->SetStatus(true, NULL, NULL);
1089 static const GLuint kClientProgramId = 1234;
1090 static const GLuint kServiceProgramId = 5679;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001091 Program* program = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001092 kClientProgramId, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001093 ASSERT_TRUE(program != NULL);
1094 EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
1095 EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
1096 EXPECT_TRUE(program->SetUniformLocationBinding(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001097 kUniform1Name, kUniform1DesiredLocation));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001098 EXPECT_TRUE(program->SetUniformLocationBinding(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001099 kUniform3BadName, kUniform3DesiredLocation));
1100
1101 static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = {
1102 { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
1103 { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, },
1104 { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
1105 };
1106 ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
1107 { kUniform1Name,
1108 kUniform1Size,
1109 kUniform1Type,
1110 kUniform1FakeLocation,
1111 kUniform1RealLocation,
1112 kUniform1DesiredLocation,
1113 kUniform1Name,
1114 },
1115 { kUniform2Name,
1116 kUniform2Size,
1117 kUniform2Type,
1118 kUniform2FakeLocation,
1119 kUniform2RealLocation,
1120 kUniform2DesiredLocation,
1121 kUniform2Name,
1122 },
1123 { kUniform3BadName,
1124 kUniform3Size,
1125 kUniform3Type,
1126 kUniform3FakeLocation,
1127 kUniform3RealLocation,
1128 kUniform3DesiredLocation,
1129 kUniform3GoodName,
1130 },
1131 };
1132
1133 const size_t kNumAttribs = arraysize(kAttribs);
1134 const size_t kNumUniforms = arraysize(kUniforms);
1135 SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
1136 kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001137 program->Link(NULL, NULL, NULL, NULL, base::Bind(&ShaderCacheCb));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001138
1139 EXPECT_EQ(kUniform1DesiredLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001140 program->GetUniformFakeLocation(kUniform1Name));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001141 EXPECT_EQ(kUniform3DesiredLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001142 program->GetUniformFakeLocation(kUniform3BadName));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001143 EXPECT_EQ(kUniform3DesiredLocation,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001144 program->GetUniformFakeLocation(kUniform3GoodName));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001145}
1146
1147class ProgramManagerWithCacheTest : public testing::Test {
1148 public:
1149 static const GLuint kClientProgramId = 1;
1150 static const GLuint kServiceProgramId = 10;
1151 static const GLuint kVertexShaderClientId = 2;
1152 static const GLuint kFragmentShaderClientId = 20;
1153 static const GLuint kVertexShaderServiceId = 3;
1154 static const GLuint kFragmentShaderServiceId = 30;
1155
1156 ProgramManagerWithCacheTest()
1157 : cache_(new MockProgramCache()),
1158 manager_(cache_.get()),
1159 vertex_shader_(NULL),
1160 fragment_shader_(NULL),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001161 program_(NULL) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001162 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001163 virtual ~ProgramManagerWithCacheTest() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001164 manager_.Destroy(false);
1165 shader_manager_.Destroy(false);
1166 }
1167
1168 protected:
1169 virtual void SetUp() {
1170 gl_.reset(new StrictMock<gfx::MockGLInterface>());
1171 ::gfx::GLInterface::SetGLInterface(gl_.get());
1172
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001173 vertex_shader_ = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001174 kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001175 fragment_shader_ = shader_manager_.CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001176 kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER);
1177 ASSERT_TRUE(vertex_shader_ != NULL);
1178 ASSERT_TRUE(fragment_shader_ != NULL);
1179 vertex_shader_->UpdateSource("lka asjf bjajsdfj");
1180 fragment_shader_->UpdateSource("lka asjf a fasgag 3rdsf3 bjajsdfj");
1181
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001182 program_ = manager_.CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001183 kClientProgramId, kServiceProgramId);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001184 ASSERT_TRUE(program_ != NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001185
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001186 program_->AttachShader(&shader_manager_, vertex_shader_);
1187 program_->AttachShader(&shader_manager_, fragment_shader_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001188 }
1189
1190 virtual void TearDown() {
1191 ::gfx::GLInterface::SetGLInterface(NULL);
1192 }
1193
1194 void SetShadersCompiled() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001195 vertex_shader_->SetStatus(true, NULL, NULL);
1196 fragment_shader_->SetStatus(true, NULL, NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001197 }
1198
1199 void SetProgramCached() {
1200 cache_->LinkedProgramCacheSuccess(
1201 vertex_shader_->source()->c_str(),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001202 NULL,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001203 fragment_shader_->source()->c_str(),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001204 NULL,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001205 &program_->bind_attrib_location_map());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001206 }
1207
1208 void SetExpectationsForProgramCached() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001209 SetExpectationsForProgramCached(program_,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001210 vertex_shader_,
1211 fragment_shader_);
1212 }
1213
1214 void SetExpectationsForProgramCached(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001215 Program* program,
1216 Shader* vertex_shader,
1217 Shader* fragment_shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001218 EXPECT_CALL(*cache_.get(), SaveLinkedProgram(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001219 program->service_id(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001220 vertex_shader,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001221 NULL,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001222 fragment_shader,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001223 NULL,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001224 &program->bind_attrib_location_map(),
1225 _)).Times(1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001226 }
1227
1228 void SetExpectationsForNotCachingProgram() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001229 SetExpectationsForNotCachingProgram(program_,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001230 vertex_shader_,
1231 fragment_shader_);
1232 }
1233
1234 void SetExpectationsForNotCachingProgram(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001235 Program* program,
1236 Shader* vertex_shader,
1237 Shader* fragment_shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001238 EXPECT_CALL(*cache_.get(), SaveLinkedProgram(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001239 program->service_id(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001240 vertex_shader,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001241 NULL,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001242 fragment_shader,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001243 NULL,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001244 &program->bind_attrib_location_map(),
1245 _)).Times(0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001246 }
1247
1248 void SetExpectationsForProgramLoad(ProgramCache::ProgramLoadResult result) {
1249 SetExpectationsForProgramLoad(kServiceProgramId,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001250 program_,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001251 vertex_shader_,
1252 fragment_shader_,
1253 result);
1254 }
1255
1256 void SetExpectationsForProgramLoad(
1257 GLuint service_program_id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001258 Program* program,
1259 Shader* vertex_shader,
1260 Shader* fragment_shader,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001261 ProgramCache::ProgramLoadResult result) {
1262 EXPECT_CALL(*cache_.get(),
1263 LoadLinkedProgram(service_program_id,
1264 vertex_shader,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001265 NULL,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001266 fragment_shader,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001267 NULL,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001268 &program->bind_attrib_location_map(),
1269 _))
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001270 .WillOnce(Return(result));
1271 }
1272
1273 void SetExpectationsForProgramLoadSuccess() {
1274 SetExpectationsForProgramLoadSuccess(kServiceProgramId);
1275 }
1276
1277 void SetExpectationsForProgramLoadSuccess(GLuint service_program_id) {
1278 TestHelper::SetupProgramSuccessExpectations(gl_.get(),
1279 NULL,
1280 0,
1281 NULL,
1282 0,
1283 service_program_id);
1284 }
1285
1286 void SetExpectationsForProgramLink() {
1287 SetExpectationsForProgramLink(kServiceProgramId);
1288 }
1289
1290 void SetExpectationsForProgramLink(GLuint service_program_id) {
1291 TestHelper::SetupShader(gl_.get(), NULL, 0, NULL, 0, service_program_id);
1292 if (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) {
1293 EXPECT_CALL(*gl_.get(),
1294 ProgramParameteri(service_program_id,
1295 PROGRAM_BINARY_RETRIEVABLE_HINT,
1296 GL_TRUE)).Times(1);
1297 }
1298 }
1299
1300 void SetExpectationsForSuccessCompile(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001301 const Shader* shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001302 const GLuint shader_id = shader->service_id();
1303 const char* src = shader->source()->c_str();
1304 EXPECT_CALL(*gl_.get(),
1305 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1);
1306 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1);
1307 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _))
1308 .WillOnce(SetArgumentPointee<2>(GL_TRUE));
1309 }
1310
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001311 void SetExpectationsForNoCompile(const Shader* shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001312 const GLuint shader_id = shader->service_id();
1313 const char* src = shader->source()->c_str();
1314 EXPECT_CALL(*gl_.get(),
1315 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0);
1316 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0);
1317 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _))
1318 .Times(0);
1319 }
1320
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001321 void SetExpectationsForErrorCompile(const Shader* shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001322 const GLuint shader_id = shader->service_id();
1323 const char* src = shader->source()->c_str();
1324 EXPECT_CALL(*gl_.get(),
1325 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1);
1326 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1);
1327 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _))
1328 .WillOnce(SetArgumentPointee<2>(GL_FALSE));
1329 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _))
1330 .WillOnce(SetArgumentPointee<2>(0));
1331 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _))
1332 .Times(1);
1333 }
1334
1335 scoped_ptr<StrictMock<gfx::MockGLInterface> > gl_;
1336
1337 scoped_ptr<MockProgramCache> cache_;
1338 ProgramManager manager_;
1339
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001340 Shader* vertex_shader_;
1341 Shader* fragment_shader_;
1342 Program* program_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001343 ShaderManager shader_manager_;
1344};
1345
1346// GCC requires these declarations, but MSVC requires they not be present
1347#ifndef COMPILER_MSVC
1348const GLuint ProgramManagerWithCacheTest::kClientProgramId;
1349const GLuint ProgramManagerWithCacheTest::kServiceProgramId;
1350const GLuint ProgramManagerWithCacheTest::kVertexShaderClientId;
1351const GLuint ProgramManagerWithCacheTest::kFragmentShaderClientId;
1352const GLuint ProgramManagerWithCacheTest::kVertexShaderServiceId;
1353const GLuint ProgramManagerWithCacheTest::kFragmentShaderServiceId;
1354#endif
1355
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001356TEST_F(ProgramManagerWithCacheTest, CacheProgramOnSuccessfulLink) {
1357 SetShadersCompiled();
1358 SetExpectationsForProgramLink();
1359 SetExpectationsForProgramCached();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001360 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, NULL,
1361 base::Bind(&ShaderCacheCb)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001362}
1363
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001364TEST_F(ProgramManagerWithCacheTest, LoadProgramOnProgramCacheHit) {
Ben Murdochbb1529c2013-08-08 10:24:53 +01001365 SetShadersCompiled();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001366 SetProgramCached();
1367
1368 SetExpectationsForNoCompile(vertex_shader_);
1369 SetExpectationsForNoCompile(fragment_shader_);
1370 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS);
1371 SetExpectationsForNotCachingProgram();
1372 SetExpectationsForProgramLoadSuccess();
1373
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001374 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, NULL,
1375 base::Bind(&ShaderCacheCb)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001376}
1377
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001378} // namespace gles2
1379} // namespace gpu