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/program_manager.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "gpu/command_buffer/common/gles2_cmd_format.h"
13 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
14 #include "gpu/command_buffer/service/common_decoder.h"
15 #include "gpu/command_buffer/service/feature_info.h"
16 #include "gpu/command_buffer/service/gpu_service_test.h"
17 #include "gpu/command_buffer/service/mocks.h"
18 #include "gpu/command_buffer/service/shader_manager.h"
19 #include "gpu/command_buffer/service/test_helper.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/gl/gl_mock.h"
24 using ::testing::DoAll
;
25 using ::testing::InSequence
;
26 using ::testing::MatcherCast
;
27 using ::testing::Pointee
;
28 using ::testing::Return
;
29 using ::testing::ReturnRef
;
30 using ::testing::SetArrayArgument
;
31 using ::testing::SetArgumentPointee
;
32 using ::testing::StrEq
;
38 const uint32 kMaxVaryingVectors
= 8;
40 void ShaderCacheCb(const std::string
& key
, const std::string
& shader
) {}
41 } // namespace anonymous
43 class ProgramManagerTest
: public GpuServiceTest
{
45 ProgramManagerTest() : manager_(NULL
, kMaxVaryingVectors
) { }
46 virtual ~ProgramManagerTest() {
47 manager_
.Destroy(false);
51 ProgramManager manager_
;
54 TEST_F(ProgramManagerTest
, Basic
) {
55 const GLuint kClient1Id
= 1;
56 const GLuint kService1Id
= 11;
57 const GLuint kClient2Id
= 2;
58 // Check we can create program.
59 manager_
.CreateProgram(kClient1Id
, kService1Id
);
60 // Check program got created.
61 Program
* program1
= manager_
.GetProgram(kClient1Id
);
62 ASSERT_TRUE(program1
!= NULL
);
64 EXPECT_TRUE(manager_
.GetClientId(program1
->service_id(), &client_id
));
65 EXPECT_EQ(kClient1Id
, client_id
);
66 // Check we get nothing for a non-existent program.
67 EXPECT_TRUE(manager_
.GetProgram(kClient2Id
) == NULL
);
70 TEST_F(ProgramManagerTest
, Destroy
) {
71 const GLuint kClient1Id
= 1;
72 const GLuint kService1Id
= 11;
73 // Check we can create program.
74 Program
* program0
= manager_
.CreateProgram(kClient1Id
, kService1Id
);
75 ASSERT_TRUE(program0
!= NULL
);
76 // Check program got created.
77 Program
* program1
= manager_
.GetProgram(kClient1Id
);
78 ASSERT_EQ(program0
, program1
);
79 EXPECT_CALL(*gl_
, DeleteProgram(kService1Id
))
81 .RetiresOnSaturation();
82 manager_
.Destroy(true);
83 // Check the resources were released.
84 program1
= manager_
.GetProgram(kClient1Id
);
85 ASSERT_TRUE(program1
== NULL
);
88 TEST_F(ProgramManagerTest
, DeleteBug
) {
89 ShaderManager shader_manager
;
90 const GLuint kClient1Id
= 1;
91 const GLuint kClient2Id
= 2;
92 const GLuint kService1Id
= 11;
93 const GLuint kService2Id
= 12;
94 // Check we can create program.
95 scoped_refptr
<Program
> program1(
96 manager_
.CreateProgram(kClient1Id
, kService1Id
));
97 scoped_refptr
<Program
> program2(
98 manager_
.CreateProgram(kClient2Id
, kService2Id
));
99 // Check program got created.
100 ASSERT_TRUE(program1
.get());
101 ASSERT_TRUE(program2
.get());
102 manager_
.UseProgram(program1
.get());
103 manager_
.MarkAsDeleted(&shader_manager
, program1
.get());
104 // Program will be deleted when last ref is released.
105 EXPECT_CALL(*gl_
, DeleteProgram(kService2Id
))
107 .RetiresOnSaturation();
108 manager_
.MarkAsDeleted(&shader_manager
, program2
.get());
109 EXPECT_TRUE(manager_
.IsOwned(program1
.get()));
110 EXPECT_FALSE(manager_
.IsOwned(program2
.get()));
113 TEST_F(ProgramManagerTest
, Program
) {
114 const GLuint kClient1Id
= 1;
115 const GLuint kService1Id
= 11;
116 // Check we can create program.
117 Program
* program1
= manager_
.CreateProgram(
118 kClient1Id
, kService1Id
);
119 ASSERT_TRUE(program1
);
120 EXPECT_EQ(kService1Id
, program1
->service_id());
121 EXPECT_FALSE(program1
->InUse());
122 EXPECT_FALSE(program1
->IsValid());
123 EXPECT_FALSE(program1
->IsDeleted());
124 EXPECT_FALSE(program1
->CanLink());
125 EXPECT_TRUE(program1
->log_info() == NULL
);
128 class ProgramManagerWithShaderTest
: public GpuServiceTest
{
130 ProgramManagerWithShaderTest()
131 : manager_(NULL
, kMaxVaryingVectors
), program_(NULL
) {
134 virtual ~ProgramManagerWithShaderTest() {
135 manager_
.Destroy(false);
136 shader_manager_
.Destroy(false);
139 static const GLint kNumVertexAttribs
= 16;
141 static const GLuint kClientProgramId
= 123;
142 static const GLuint kServiceProgramId
= 456;
143 static const GLuint kVertexShaderClientId
= 201;
144 static const GLuint kFragmentShaderClientId
= 202;
145 static const GLuint kVertexShaderServiceId
= 301;
146 static const GLuint kFragmentShaderServiceId
= 302;
148 static const char* kAttrib1Name
;
149 static const char* kAttrib2Name
;
150 static const char* kAttrib3Name
;
151 static const GLint kAttrib1Size
= 1;
152 static const GLint kAttrib2Size
= 1;
153 static const GLint kAttrib3Size
= 1;
154 static const int kAttrib1Precision
= SH_PRECISION_MEDIUMP
;
155 static const int kAttrib2Precision
= SH_PRECISION_HIGHP
;
156 static const int kAttrib3Precision
= SH_PRECISION_LOWP
;
157 static const int kAttribStaticUse
= 0;
158 static const GLint kAttrib1Location
= 0;
159 static const GLint kAttrib2Location
= 1;
160 static const GLint kAttrib3Location
= 2;
161 static const GLenum kAttrib1Type
= GL_FLOAT_VEC4
;
162 static const GLenum kAttrib2Type
= GL_FLOAT_VEC2
;
163 static const GLenum kAttrib3Type
= GL_FLOAT_VEC3
;
164 static const GLint kInvalidAttribLocation
= 30;
165 static const GLint kBadAttribIndex
= kNumVertexAttribs
;
167 static const char* kUniform1Name
;
168 static const char* kUniform2Name
;
169 static const char* kUniform3BadName
;
170 static const char* kUniform3GoodName
;
171 static const GLint kUniform1Size
= 1;
172 static const GLint kUniform2Size
= 3;
173 static const GLint kUniform3Size
= 2;
174 static const int kUniform1Precision
= SH_PRECISION_LOWP
;
175 static const int kUniform2Precision
= SH_PRECISION_MEDIUMP
;
176 static const int kUniform3Precision
= SH_PRECISION_HIGHP
;
177 static const int kUniform1StaticUse
= 1;
178 static const int kUniform2StaticUse
= 1;
179 static const int kUniform3StaticUse
= 1;
180 static const GLint kUniform1FakeLocation
= 0; // These are hard coded
181 static const GLint kUniform2FakeLocation
= 1; // to match
182 static const GLint kUniform3FakeLocation
= 2; // ProgramManager.
183 static const GLint kUniform1RealLocation
= 11;
184 static const GLint kUniform2RealLocation
= 22;
185 static const GLint kUniform3RealLocation
= 33;
186 static const GLint kUniform1DesiredLocation
= -1;
187 static const GLint kUniform2DesiredLocation
= -1;
188 static const GLint kUniform3DesiredLocation
= -1;
189 static const GLenum kUniform1Type
= GL_FLOAT_VEC4
;
190 static const GLenum kUniform2Type
= GL_INT_VEC2
;
191 static const GLenum kUniform3Type
= GL_FLOAT_VEC3
;
192 static const GLint kInvalidUniformLocation
= 30;
193 static const GLint kBadUniformIndex
= 1000;
195 static const size_t kNumAttribs
;
196 static const size_t kNumUniforms
;
199 typedef TestHelper::AttribInfo AttribInfo
;
200 typedef TestHelper::UniformInfo UniformInfo
;
214 VarCategory category
;
217 virtual void SetUp() {
218 GpuServiceTest::SetUp();
220 SetupDefaultShaderExpectations();
222 Shader
* vertex_shader
= shader_manager_
.CreateShader(
223 kVertexShaderClientId
, kVertexShaderServiceId
, GL_VERTEX_SHADER
);
224 Shader
* fragment_shader
=
225 shader_manager_
.CreateShader(
226 kFragmentShaderClientId
, kFragmentShaderServiceId
,
228 ASSERT_TRUE(vertex_shader
!= NULL
);
229 ASSERT_TRUE(fragment_shader
!= NULL
);
230 TestHelper::SetShaderStates(gl_
.get(), vertex_shader
, true);
231 TestHelper::SetShaderStates(gl_
.get(), fragment_shader
, true);
233 program_
= manager_
.CreateProgram(
234 kClientProgramId
, kServiceProgramId
);
235 ASSERT_TRUE(program_
!= NULL
);
237 program_
->AttachShader(&shader_manager_
, vertex_shader
);
238 program_
->AttachShader(&shader_manager_
, fragment_shader
);
239 program_
->Link(NULL
, NULL
, NULL
, Program::kCountOnlyStaticallyUsed
,
240 base::Bind(&ShaderCacheCb
));
243 void SetupShader(AttribInfo
* attribs
, size_t num_attribs
,
244 UniformInfo
* uniforms
, size_t num_uniforms
,
246 TestHelper::SetupShader(
247 gl_
.get(), attribs
, num_attribs
, uniforms
, num_uniforms
, service_id
);
250 void SetupDefaultShaderExpectations() {
251 SetupShader(kAttribs
, kNumAttribs
, kUniforms
, kNumUniforms
,
255 void SetupExpectationsForClearingUniforms(
256 UniformInfo
* uniforms
, size_t num_uniforms
) {
257 TestHelper::SetupExpectationsForClearingUniforms(
258 gl_
.get(), uniforms
, num_uniforms
);
261 // Return true if link status matches expected_link_status
262 bool LinkAsExpected(Program
* program
,
263 bool expected_link_status
) {
264 GLuint service_id
= program
->service_id();
265 if (expected_link_status
) {
266 SetupShader(kAttribs
, kNumAttribs
, kUniforms
, kNumUniforms
,
269 program
->Link(NULL
, NULL
, NULL
, Program::kCountOnlyStaticallyUsed
,
270 base::Bind(&ShaderCacheCb
));
272 program
->GetProgramiv(GL_LINK_STATUS
, &link_status
);
273 return (static_cast<bool>(link_status
) == expected_link_status
);
276 Program
* SetupShaderVariableTest(const VarInfo
* vertex_variables
,
277 size_t vertex_variable_size
,
278 const VarInfo
* fragment_variables
,
279 size_t fragment_variable_size
) {
281 const GLuint kVShaderClientId
= 1;
282 const GLuint kVShaderServiceId
= 11;
283 const GLuint kFShaderClientId
= 2;
284 const GLuint kFShaderServiceId
= 12;
286 ShaderTranslator::VariableMap vertex_attrib_map
;
287 ShaderTranslator::VariableMap vertex_uniform_map
;
288 ShaderTranslator::VariableMap vertex_varying_map
;
289 for (size_t ii
= 0; ii
< vertex_variable_size
; ++ii
) {
290 ShaderTranslator::VariableMap
* map
= NULL
;
291 switch (vertex_variables
[ii
].category
) {
293 map
= &vertex_attrib_map
;
296 map
= &vertex_uniform_map
;
299 map
= &vertex_varying_map
;
304 (*map
)[vertex_variables
[ii
].name
] =
305 ShaderTranslator::VariableInfo(vertex_variables
[ii
].type
,
306 vertex_variables
[ii
].size
,
307 vertex_variables
[ii
].precision
,
308 vertex_variables
[ii
].static_use
,
309 vertex_variables
[ii
].name
);
312 ShaderTranslator::VariableMap frag_attrib_map
;
313 ShaderTranslator::VariableMap frag_uniform_map
;
314 ShaderTranslator::VariableMap frag_varying_map
;
315 for (size_t ii
= 0; ii
< fragment_variable_size
; ++ii
) {
316 ShaderTranslator::VariableMap
* map
= NULL
;
317 switch (fragment_variables
[ii
].category
) {
319 map
= &frag_attrib_map
;
322 map
= &frag_uniform_map
;
325 map
= &frag_varying_map
;
330 (*map
)[fragment_variables
[ii
].name
] =
331 ShaderTranslator::VariableInfo(fragment_variables
[ii
].type
,
332 fragment_variables
[ii
].size
,
333 fragment_variables
[ii
].precision
,
334 fragment_variables
[ii
].static_use
,
335 fragment_variables
[ii
].name
);
338 // Check we can create shader.
339 Shader
* vshader
= shader_manager_
.CreateShader(
340 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
341 Shader
* fshader
= shader_manager_
.CreateShader(
342 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
343 // Check shader got created.
344 EXPECT_TRUE(vshader
!= NULL
&& fshader
!= NULL
);
346 TestHelper::SetShaderStates(
347 gl_
.get(), vshader
, true, NULL
, NULL
,
348 &vertex_attrib_map
, &vertex_uniform_map
, &vertex_varying_map
, NULL
);
349 TestHelper::SetShaderStates(
350 gl_
.get(), fshader
, true, NULL
, NULL
,
351 &frag_attrib_map
, &frag_uniform_map
, &frag_varying_map
, NULL
);
354 const GLuint kClientProgramId
= 6666;
355 const GLuint kServiceProgramId
= 8888;
357 manager_
.CreateProgram(kClientProgramId
, kServiceProgramId
);
358 EXPECT_TRUE(program
!= NULL
);
359 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
360 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
364 static AttribInfo kAttribs
[];
365 static UniformInfo kUniforms
[];
367 ProgramManager manager_
;
369 ShaderManager shader_manager_
;
372 ProgramManagerWithShaderTest::AttribInfo
373 ProgramManagerWithShaderTest::kAttribs
[] = {
374 { kAttrib1Name
, kAttrib1Size
, kAttrib1Type
, kAttrib1Location
, },
375 { kAttrib2Name
, kAttrib2Size
, kAttrib2Type
, kAttrib2Location
, },
376 { kAttrib3Name
, kAttrib3Size
, kAttrib3Type
, kAttrib3Location
, },
379 // GCC requires these declarations, but MSVC requires they not be present
380 #ifndef COMPILER_MSVC
381 const GLint
ProgramManagerWithShaderTest::kNumVertexAttribs
;
382 const GLuint
ProgramManagerWithShaderTest::kClientProgramId
;
383 const GLuint
ProgramManagerWithShaderTest::kServiceProgramId
;
384 const GLuint
ProgramManagerWithShaderTest::kVertexShaderClientId
;
385 const GLuint
ProgramManagerWithShaderTest::kFragmentShaderClientId
;
386 const GLuint
ProgramManagerWithShaderTest::kVertexShaderServiceId
;
387 const GLuint
ProgramManagerWithShaderTest::kFragmentShaderServiceId
;
388 const GLint
ProgramManagerWithShaderTest::kAttrib1Size
;
389 const GLint
ProgramManagerWithShaderTest::kAttrib2Size
;
390 const GLint
ProgramManagerWithShaderTest::kAttrib3Size
;
391 const GLint
ProgramManagerWithShaderTest::kAttrib1Location
;
392 const GLint
ProgramManagerWithShaderTest::kAttrib2Location
;
393 const GLint
ProgramManagerWithShaderTest::kAttrib3Location
;
394 const GLenum
ProgramManagerWithShaderTest::kAttrib1Type
;
395 const GLenum
ProgramManagerWithShaderTest::kAttrib2Type
;
396 const GLenum
ProgramManagerWithShaderTest::kAttrib3Type
;
397 const GLint
ProgramManagerWithShaderTest::kInvalidAttribLocation
;
398 const GLint
ProgramManagerWithShaderTest::kBadAttribIndex
;
399 const GLint
ProgramManagerWithShaderTest::kUniform1Size
;
400 const GLint
ProgramManagerWithShaderTest::kUniform2Size
;
401 const GLint
ProgramManagerWithShaderTest::kUniform3Size
;
402 const GLint
ProgramManagerWithShaderTest::kUniform1FakeLocation
;
403 const GLint
ProgramManagerWithShaderTest::kUniform2FakeLocation
;
404 const GLint
ProgramManagerWithShaderTest::kUniform3FakeLocation
;
405 const GLint
ProgramManagerWithShaderTest::kUniform1RealLocation
;
406 const GLint
ProgramManagerWithShaderTest::kUniform2RealLocation
;
407 const GLint
ProgramManagerWithShaderTest::kUniform3RealLocation
;
408 const GLint
ProgramManagerWithShaderTest::kUniform1DesiredLocation
;
409 const GLint
ProgramManagerWithShaderTest::kUniform2DesiredLocation
;
410 const GLint
ProgramManagerWithShaderTest::kUniform3DesiredLocation
;
411 const GLenum
ProgramManagerWithShaderTest::kUniform1Type
;
412 const GLenum
ProgramManagerWithShaderTest::kUniform2Type
;
413 const GLenum
ProgramManagerWithShaderTest::kUniform3Type
;
414 const GLint
ProgramManagerWithShaderTest::kInvalidUniformLocation
;
415 const GLint
ProgramManagerWithShaderTest::kBadUniformIndex
;
418 const size_t ProgramManagerWithShaderTest::kNumAttribs
=
419 arraysize(ProgramManagerWithShaderTest::kAttribs
);
421 ProgramManagerWithShaderTest::UniformInfo
422 ProgramManagerWithShaderTest::kUniforms
[] = {
426 kUniform1FakeLocation
,
427 kUniform1RealLocation
,
428 kUniform1DesiredLocation
,
434 kUniform2FakeLocation
,
435 kUniform2RealLocation
,
436 kUniform2DesiredLocation
,
442 kUniform3FakeLocation
,
443 kUniform3RealLocation
,
444 kUniform3DesiredLocation
,
449 const size_t ProgramManagerWithShaderTest::kNumUniforms
=
450 arraysize(ProgramManagerWithShaderTest::kUniforms
);
452 const char* ProgramManagerWithShaderTest::kAttrib1Name
= "attrib1";
453 const char* ProgramManagerWithShaderTest::kAttrib2Name
= "attrib2";
454 const char* ProgramManagerWithShaderTest::kAttrib3Name
= "attrib3";
455 const char* ProgramManagerWithShaderTest::kUniform1Name
= "uniform1";
456 // Correctly has array spec.
457 const char* ProgramManagerWithShaderTest::kUniform2Name
= "uniform2[0]";
458 // Incorrectly missing array spec.
459 const char* ProgramManagerWithShaderTest::kUniform3BadName
= "uniform3";
460 const char* ProgramManagerWithShaderTest::kUniform3GoodName
= "uniform3[0]";
462 TEST_F(ProgramManagerWithShaderTest
, GetAttribInfos
) {
463 const Program
* program
= manager_
.GetProgram(kClientProgramId
);
464 ASSERT_TRUE(program
!= NULL
);
465 const Program::AttribInfoVector
& infos
=
466 program
->GetAttribInfos();
467 ASSERT_EQ(kNumAttribs
, infos
.size());
468 for (size_t ii
= 0; ii
< kNumAttribs
; ++ii
) {
469 const Program::VertexAttrib
& info
= infos
[ii
];
470 const AttribInfo
& expected
= kAttribs
[ii
];
471 EXPECT_EQ(expected
.size
, info
.size
);
472 EXPECT_EQ(expected
.type
, info
.type
);
473 EXPECT_EQ(expected
.location
, info
.location
);
474 EXPECT_STREQ(expected
.name
, info
.name
.c_str());
478 TEST_F(ProgramManagerWithShaderTest
, GetAttribInfo
) {
479 const GLint kValidIndex
= 1;
480 const GLint kInvalidIndex
= 1000;
481 const Program
* program
= manager_
.GetProgram(kClientProgramId
);
482 ASSERT_TRUE(program
!= NULL
);
483 const Program::VertexAttrib
* info
=
484 program
->GetAttribInfo(kValidIndex
);
485 ASSERT_TRUE(info
!= NULL
);
486 EXPECT_EQ(kAttrib2Size
, info
->size
);
487 EXPECT_EQ(kAttrib2Type
, info
->type
);
488 EXPECT_EQ(kAttrib2Location
, info
->location
);
489 EXPECT_STREQ(kAttrib2Name
, info
->name
.c_str());
490 EXPECT_TRUE(program
->GetAttribInfo(kInvalidIndex
) == NULL
);
493 TEST_F(ProgramManagerWithShaderTest
, GetAttribLocation
) {
494 const char* kInvalidName
= "foo";
495 const Program
* program
= manager_
.GetProgram(kClientProgramId
);
496 ASSERT_TRUE(program
!= NULL
);
497 EXPECT_EQ(kAttrib2Location
, program
->GetAttribLocation(kAttrib2Name
));
498 EXPECT_EQ(-1, program
->GetAttribLocation(kInvalidName
));
501 TEST_F(ProgramManagerWithShaderTest
, GetUniformInfo
) {
502 const GLint kInvalidIndex
= 1000;
503 const Program
* program
= manager_
.GetProgram(kClientProgramId
);
504 ASSERT_TRUE(program
!= NULL
);
505 const Program::UniformInfo
* info
=
506 program
->GetUniformInfo(0);
507 ASSERT_TRUE(info
!= NULL
);
508 EXPECT_EQ(kUniform1Size
, info
->size
);
509 EXPECT_EQ(kUniform1Type
, info
->type
);
510 EXPECT_EQ(kUniform1RealLocation
, info
->element_locations
[0]);
511 EXPECT_STREQ(kUniform1Name
, info
->name
.c_str());
512 info
= program
->GetUniformInfo(1);
513 ASSERT_TRUE(info
!= NULL
);
514 EXPECT_EQ(kUniform2Size
, info
->size
);
515 EXPECT_EQ(kUniform2Type
, info
->type
);
516 EXPECT_EQ(kUniform2RealLocation
, info
->element_locations
[0]);
517 EXPECT_STREQ(kUniform2Name
, info
->name
.c_str());
518 info
= program
->GetUniformInfo(2);
519 // We emulate certain OpenGL drivers by supplying the name without
520 // the array spec. Our implementation should correctly add the required spec.
521 ASSERT_TRUE(info
!= NULL
);
522 EXPECT_EQ(kUniform3Size
, info
->size
);
523 EXPECT_EQ(kUniform3Type
, info
->type
);
524 EXPECT_EQ(kUniform3RealLocation
, info
->element_locations
[0]);
525 EXPECT_STREQ(kUniform3GoodName
, info
->name
.c_str());
526 EXPECT_TRUE(program
->GetUniformInfo(kInvalidIndex
) == NULL
);
529 TEST_F(ProgramManagerWithShaderTest
, AttachDetachShader
) {
530 static const GLuint kClientProgramId
= 124;
531 static const GLuint kServiceProgramId
= 457;
532 Program
* program
= manager_
.CreateProgram(
533 kClientProgramId
, kServiceProgramId
);
534 ASSERT_TRUE(program
!= NULL
);
535 EXPECT_FALSE(program
->CanLink());
536 const GLuint kVShaderClientId
= 2001;
537 const GLuint kFShaderClientId
= 2002;
538 const GLuint kVShaderServiceId
= 3001;
539 const GLuint kFShaderServiceId
= 3002;
540 Shader
* vshader
= shader_manager_
.CreateShader(
541 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
542 ASSERT_TRUE(vshader
!= NULL
);
543 TestHelper::SetShaderStates(gl_
.get(), vshader
, true);
544 Shader
* fshader
= shader_manager_
.CreateShader(
545 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
546 ASSERT_TRUE(fshader
!= NULL
);
547 TestHelper::SetShaderStates(gl_
.get(), fshader
, true);
548 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
549 EXPECT_FALSE(program
->CanLink());
550 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
551 EXPECT_TRUE(program
->CanLink());
552 program
->DetachShader(&shader_manager_
, vshader
);
553 EXPECT_FALSE(program
->CanLink());
554 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
555 EXPECT_TRUE(program
->CanLink());
556 program
->DetachShader(&shader_manager_
, fshader
);
557 EXPECT_FALSE(program
->CanLink());
558 EXPECT_FALSE(program
->AttachShader(&shader_manager_
, vshader
));
559 EXPECT_FALSE(program
->CanLink());
560 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
561 EXPECT_TRUE(program
->CanLink());
562 TestHelper::SetShaderStates(gl_
.get(), vshader
, false);
563 EXPECT_FALSE(program
->CanLink());
564 TestHelper::SetShaderStates(gl_
.get(), vshader
, true);
565 EXPECT_TRUE(program
->CanLink());
566 TestHelper::SetShaderStates(gl_
.get(), fshader
, false);
567 EXPECT_FALSE(program
->CanLink());
568 TestHelper::SetShaderStates(gl_
.get(), fshader
, true);
569 EXPECT_TRUE(program
->CanLink());
570 EXPECT_TRUE(program
->DetachShader(&shader_manager_
, fshader
));
571 EXPECT_FALSE(program
->DetachShader(&shader_manager_
, fshader
));
574 TEST_F(ProgramManagerWithShaderTest
, GetUniformFakeLocation
) {
575 const Program
* program
= manager_
.GetProgram(kClientProgramId
);
576 ASSERT_TRUE(program
!= NULL
);
577 // Emulate the situation that uniform3[1] isn't used and optimized out by
578 // a driver, so it's location is -1.
579 Program::UniformInfo
* uniform
= const_cast<Program::UniformInfo
*>(
580 program
->GetUniformInfo(2));
581 ASSERT_TRUE(uniform
!= NULL
&& kUniform3Size
== 2);
582 EXPECT_EQ(kUniform3Size
, uniform
->size
);
583 uniform
->element_locations
[1] = -1;
584 EXPECT_EQ(kUniform1FakeLocation
,
585 program
->GetUniformFakeLocation(kUniform1Name
));
586 EXPECT_EQ(kUniform2FakeLocation
,
587 program
->GetUniformFakeLocation(kUniform2Name
));
588 EXPECT_EQ(kUniform3FakeLocation
,
589 program
->GetUniformFakeLocation(kUniform3BadName
));
590 // Check we can get uniform2 as "uniform2" even though the name is
592 EXPECT_EQ(kUniform2FakeLocation
,
593 program
->GetUniformFakeLocation("uniform2"));
594 // Check we can get uniform3 as "uniform3[0]" even though we simulated GL
595 // returning "uniform3"
596 EXPECT_EQ(kUniform3FakeLocation
,
597 program
->GetUniformFakeLocation(kUniform3GoodName
));
598 // Check that we can get the locations of the array elements > 1
599 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation
, 1),
600 program
->GetUniformFakeLocation("uniform2[1]"));
601 EXPECT_EQ(ProgramManager::MakeFakeLocation(kUniform2FakeLocation
, 2),
602 program
->GetUniformFakeLocation("uniform2[2]"));
603 EXPECT_EQ(-1, program
->GetUniformFakeLocation("uniform2[3]"));
604 EXPECT_EQ(-1, program
->GetUniformFakeLocation("uniform3[1]"));
605 EXPECT_EQ(-1, program
->GetUniformFakeLocation("uniform3[2]"));
608 TEST_F(ProgramManagerWithShaderTest
, GetUniformInfoByFakeLocation
) {
609 const GLint kInvalidLocation
= 1234;
610 const Program::UniformInfo
* info
;
611 const Program
* program
= manager_
.GetProgram(kClientProgramId
);
612 GLint real_location
= -1;
613 GLint array_index
= -1;
614 ASSERT_TRUE(program
!= NULL
);
615 info
= program
->GetUniformInfoByFakeLocation(
616 kUniform2FakeLocation
, &real_location
, &array_index
);
617 EXPECT_EQ(kUniform2RealLocation
, real_location
);
618 EXPECT_EQ(0, array_index
);
619 ASSERT_TRUE(info
!= NULL
);
620 EXPECT_EQ(kUniform2Type
, info
->type
);
623 info
= program
->GetUniformInfoByFakeLocation(
624 kInvalidLocation
, &real_location
, &array_index
);
625 EXPECT_TRUE(info
== NULL
);
626 EXPECT_EQ(-1, real_location
);
627 EXPECT_EQ(-1, array_index
);
628 GLint loc
= program
->GetUniformFakeLocation("uniform2[2]");
629 info
= program
->GetUniformInfoByFakeLocation(
630 loc
, &real_location
, &array_index
);
631 ASSERT_TRUE(info
!= NULL
);
632 EXPECT_EQ(kUniform2RealLocation
+ 2 * 2, real_location
);
633 EXPECT_EQ(2, array_index
);
636 // Some GL drivers incorrectly return gl_DepthRange and possibly other uniforms
637 // that start with "gl_". Our implementation catches these and does not allow
638 // them back to client.
639 TEST_F(ProgramManagerWithShaderTest
, GLDriverReturnsGLUnderscoreUniform
) {
640 static const char* kUniform2Name
= "gl_longNameWeCanCheckFor";
641 static ProgramManagerWithShaderTest::UniformInfo kUniforms
[] = {
645 kUniform1FakeLocation
,
646 kUniform1RealLocation
,
647 kUniform1DesiredLocation
,
653 kUniform2FakeLocation
,
654 kUniform2RealLocation
,
655 kUniform2DesiredLocation
,
661 kUniform3FakeLocation
,
662 kUniform3RealLocation
,
663 kUniform3DesiredLocation
,
667 const size_t kNumUniforms
= arraysize(kUniforms
);
668 static const GLuint kClientProgramId
= 1234;
669 static const GLuint kServiceProgramId
= 5679;
670 const GLuint kVShaderClientId
= 2001;
671 const GLuint kFShaderClientId
= 2002;
672 const GLuint kVShaderServiceId
= 3001;
673 const GLuint kFShaderServiceId
= 3002;
675 kAttribs
, kNumAttribs
, kUniforms
, kNumUniforms
, kServiceProgramId
);
676 Shader
* vshader
= shader_manager_
.CreateShader(
677 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
678 ASSERT_TRUE(vshader
!= NULL
);
679 TestHelper::SetShaderStates(gl_
.get(), vshader
, true);
680 Shader
* fshader
= shader_manager_
.CreateShader(
681 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
682 ASSERT_TRUE(fshader
!= NULL
);
683 TestHelper::SetShaderStates(gl_
.get(), fshader
, true);
685 manager_
.CreateProgram(kClientProgramId
, kServiceProgramId
);
686 ASSERT_TRUE(program
!= NULL
);
687 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
688 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
689 program
->Link(NULL
, NULL
, NULL
, Program::kCountOnlyStaticallyUsed
,
690 base::Bind(&ShaderCacheCb
));
692 program
->GetProgramiv(GL_ACTIVE_ATTRIBUTES
, &value
);
694 // Check that we skipped the "gl_" uniform.
695 program
->GetProgramiv(GL_ACTIVE_UNIFORMS
, &value
);
697 // Check that our max length adds room for the array spec and is not as long
698 // as the "gl_" uniform we skipped.
699 // +4u is to account for "gl_" and NULL terminator.
700 program
->GetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH
, &value
);
701 EXPECT_EQ(strlen(kUniform3BadName
) + 4u, static_cast<size_t>(value
));
704 // Test the bug comparing similar array names is fixed.
705 TEST_F(ProgramManagerWithShaderTest
, SimilarArrayNames
) {
706 static const char* kUniform2Name
= "u_nameLong[0]";
707 static const char* kUniform3Name
= "u_name[0]";
708 static const GLint kUniform2Size
= 2;
709 static const GLint kUniform3Size
= 2;
710 static ProgramManagerWithShaderTest::UniformInfo kUniforms
[] = {
714 kUniform1FakeLocation
,
715 kUniform1RealLocation
,
716 kUniform1DesiredLocation
,
722 kUniform2FakeLocation
,
723 kUniform2RealLocation
,
724 kUniform2DesiredLocation
,
730 kUniform3FakeLocation
,
731 kUniform3RealLocation
,
732 kUniform3DesiredLocation
,
736 const size_t kNumUniforms
= arraysize(kUniforms
);
737 static const GLuint kClientProgramId
= 1234;
738 static const GLuint kServiceProgramId
= 5679;
739 const GLuint kVShaderClientId
= 2001;
740 const GLuint kFShaderClientId
= 2002;
741 const GLuint kVShaderServiceId
= 3001;
742 const GLuint kFShaderServiceId
= 3002;
744 kAttribs
, kNumAttribs
, kUniforms
, kNumUniforms
, kServiceProgramId
);
745 Shader
* vshader
= shader_manager_
.CreateShader(
746 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
747 ASSERT_TRUE(vshader
!= NULL
);
748 TestHelper::SetShaderStates(gl_
.get(), vshader
, true);
749 Shader
* fshader
= shader_manager_
.CreateShader(
750 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
751 ASSERT_TRUE(fshader
!= NULL
);
752 TestHelper::SetShaderStates(gl_
.get(), fshader
, true);
754 manager_
.CreateProgram(kClientProgramId
, kServiceProgramId
);
755 ASSERT_TRUE(program
!= NULL
);
756 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
757 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
758 program
->Link(NULL
, NULL
, NULL
, Program::kCountOnlyStaticallyUsed
,
759 base::Bind(&ShaderCacheCb
));
761 // Check that we get the correct locations.
762 EXPECT_EQ(kUniform2FakeLocation
,
763 program
->GetUniformFakeLocation(kUniform2Name
));
764 EXPECT_EQ(kUniform3FakeLocation
,
765 program
->GetUniformFakeLocation(kUniform3Name
));
768 // Some GL drivers incorrectly return the wrong type. For example they return
769 // GL_FLOAT_VEC2 when they should return GL_FLOAT_MAT2. Check we handle this.
770 TEST_F(ProgramManagerWithShaderTest
, GLDriverReturnsWrongTypeInfo
) {
771 static GLenum kAttrib2BadType
= GL_FLOAT_VEC2
;
772 static GLenum kAttrib2GoodType
= GL_FLOAT_MAT2
;
773 static GLenum kUniform2BadType
= GL_FLOAT_VEC3
;
774 static GLenum kUniform2GoodType
= GL_FLOAT_MAT3
;
775 ShaderTranslator::VariableMap attrib_map
;
776 ShaderTranslator::VariableMap uniform_map
;
777 ShaderTranslator::VariableMap varying_map
;
778 attrib_map
[kAttrib1Name
] = ShaderTranslatorInterface::VariableInfo(
779 kAttrib1Type
, kAttrib1Size
, kAttrib1Precision
,
780 kAttribStaticUse
, kAttrib1Name
);
781 attrib_map
[kAttrib2Name
] = ShaderTranslatorInterface::VariableInfo(
782 kAttrib2GoodType
, kAttrib2Size
, kAttrib2Precision
,
783 kAttribStaticUse
, kAttrib2Name
);
784 attrib_map
[kAttrib3Name
] = ShaderTranslatorInterface::VariableInfo(
785 kAttrib3Type
, kAttrib3Size
, kAttrib3Precision
,
786 kAttribStaticUse
, kAttrib3Name
);
787 uniform_map
[kUniform1Name
] = ShaderTranslatorInterface::VariableInfo(
788 kUniform1Type
, kUniform1Size
, kUniform1Precision
,
789 kUniform1StaticUse
, kUniform1Name
);
790 uniform_map
[kUniform2Name
] = ShaderTranslatorInterface::VariableInfo(
791 kUniform2GoodType
, kUniform2Size
, kUniform2Precision
,
792 kUniform2StaticUse
, kUniform2Name
);
793 uniform_map
[kUniform3GoodName
] = ShaderTranslatorInterface::VariableInfo(
794 kUniform3Type
, kUniform3Size
, kUniform3Precision
,
795 kUniform3StaticUse
, kUniform3GoodName
);
796 const GLuint kVShaderClientId
= 2001;
797 const GLuint kFShaderClientId
= 2002;
798 const GLuint kVShaderServiceId
= 3001;
799 const GLuint kFShaderServiceId
= 3002;
800 Shader
* vshader
= shader_manager_
.CreateShader(
801 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
802 ASSERT_TRUE(vshader
!= NULL
);
803 TestHelper::SetShaderStates(
804 gl_
.get(), vshader
, true, NULL
, NULL
,
805 &attrib_map
, &uniform_map
, &varying_map
, NULL
);
806 Shader
* fshader
= shader_manager_
.CreateShader(
807 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
808 ASSERT_TRUE(fshader
!= NULL
);
809 TestHelper::SetShaderStates(
810 gl_
.get(), fshader
, true, NULL
, NULL
,
811 &attrib_map
, &uniform_map
, &varying_map
, NULL
);
812 static ProgramManagerWithShaderTest::AttribInfo kAttribs
[] = {
813 { kAttrib1Name
, kAttrib1Size
, kAttrib1Type
, kAttrib1Location
, },
814 { kAttrib2Name
, kAttrib2Size
, kAttrib2BadType
, kAttrib2Location
, },
815 { kAttrib3Name
, kAttrib3Size
, kAttrib3Type
, kAttrib3Location
, },
817 static ProgramManagerWithShaderTest::UniformInfo kUniforms
[] = {
821 kUniform1FakeLocation
,
822 kUniform1RealLocation
,
823 kUniform1DesiredLocation
,
829 kUniform2FakeLocation
,
830 kUniform2RealLocation
,
831 kUniform2DesiredLocation
,
837 kUniform3FakeLocation
,
838 kUniform3RealLocation
,
839 kUniform3DesiredLocation
,
843 const size_t kNumAttribs
= arraysize(kAttribs
);
844 const size_t kNumUniforms
= arraysize(kUniforms
);
845 static const GLuint kClientProgramId
= 1234;
846 static const GLuint kServiceProgramId
= 5679;
847 SetupShader(kAttribs
, kNumAttribs
, kUniforms
, kNumUniforms
,
849 Program
* program
= manager_
.CreateProgram(
850 kClientProgramId
, kServiceProgramId
);
851 ASSERT_TRUE(program
!= NULL
);
852 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
853 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
854 program
->Link(NULL
, NULL
, NULL
, Program::kCountOnlyStaticallyUsed
,
855 base::Bind(&ShaderCacheCb
));
856 // Check that we got the good type, not the bad.
858 for (unsigned index
= 0; index
< kNumAttribs
; ++index
) {
859 const Program::VertexAttrib
* attrib_info
=
860 program
->GetAttribInfo(index
);
861 ASSERT_TRUE(attrib_info
!= NULL
);
862 ShaderTranslator::VariableMap::const_iterator it
= attrib_map
.find(
864 ASSERT_TRUE(it
!= attrib_map
.end());
865 EXPECT_EQ(it
->first
, attrib_info
->name
);
866 EXPECT_EQ(static_cast<GLenum
>(it
->second
.type
), attrib_info
->type
);
867 EXPECT_EQ(it
->second
.size
, attrib_info
->size
);
868 EXPECT_EQ(it
->second
.name
, attrib_info
->name
);
871 for (unsigned index
= 0; index
< kNumUniforms
; ++index
) {
872 const Program::UniformInfo
* uniform_info
=
873 program
->GetUniformInfo(index
);
874 ASSERT_TRUE(uniform_info
!= NULL
);
875 ShaderTranslator::VariableMap::const_iterator it
= uniform_map
.find(
877 ASSERT_TRUE(it
!= uniform_map
.end());
878 EXPECT_EQ(it
->first
, uniform_info
->name
);
879 EXPECT_EQ(static_cast<GLenum
>(it
->second
.type
), uniform_info
->type
);
880 EXPECT_EQ(it
->second
.size
, uniform_info
->size
);
881 EXPECT_EQ(it
->second
.name
, uniform_info
->name
);
885 TEST_F(ProgramManagerWithShaderTest
, ProgramInfoUseCount
) {
886 static const GLuint kClientProgramId
= 124;
887 static const GLuint kServiceProgramId
= 457;
888 Program
* program
= manager_
.CreateProgram(
889 kClientProgramId
, kServiceProgramId
);
890 ASSERT_TRUE(program
!= NULL
);
891 EXPECT_FALSE(program
->CanLink());
892 const GLuint kVShaderClientId
= 2001;
893 const GLuint kFShaderClientId
= 2002;
894 const GLuint kVShaderServiceId
= 3001;
895 const GLuint kFShaderServiceId
= 3002;
896 Shader
* vshader
= shader_manager_
.CreateShader(
897 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
898 ASSERT_TRUE(vshader
!= NULL
);
899 TestHelper::SetShaderStates(gl_
.get(), vshader
, true);
900 Shader
* fshader
= shader_manager_
.CreateShader(
901 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
902 ASSERT_TRUE(fshader
!= NULL
);
903 TestHelper::SetShaderStates(gl_
.get(), fshader
, true);
904 EXPECT_FALSE(vshader
->InUse());
905 EXPECT_FALSE(fshader
->InUse());
906 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
907 EXPECT_TRUE(vshader
->InUse());
908 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
909 EXPECT_TRUE(fshader
->InUse());
910 EXPECT_TRUE(program
->CanLink());
911 EXPECT_FALSE(program
->InUse());
912 EXPECT_FALSE(program
->IsDeleted());
913 manager_
.UseProgram(program
);
914 EXPECT_TRUE(program
->InUse());
915 manager_
.UseProgram(program
);
916 EXPECT_TRUE(program
->InUse());
917 manager_
.MarkAsDeleted(&shader_manager_
, program
);
918 EXPECT_TRUE(program
->IsDeleted());
919 Program
* info2
= manager_
.GetProgram(kClientProgramId
);
920 EXPECT_EQ(program
, info2
);
921 manager_
.UnuseProgram(&shader_manager_
, program
);
922 EXPECT_TRUE(program
->InUse());
923 // this should delete the info.
924 EXPECT_CALL(*gl_
, DeleteProgram(kServiceProgramId
))
926 .RetiresOnSaturation();
927 manager_
.UnuseProgram(&shader_manager_
, program
);
928 info2
= manager_
.GetProgram(kClientProgramId
);
929 EXPECT_TRUE(info2
== NULL
);
930 EXPECT_FALSE(vshader
->InUse());
931 EXPECT_FALSE(fshader
->InUse());
934 TEST_F(ProgramManagerWithShaderTest
, ProgramInfoUseCount2
) {
935 static const GLuint kClientProgramId
= 124;
936 static const GLuint kServiceProgramId
= 457;
937 Program
* program
= manager_
.CreateProgram(
938 kClientProgramId
, kServiceProgramId
);
939 ASSERT_TRUE(program
!= NULL
);
940 EXPECT_FALSE(program
->CanLink());
941 const GLuint kVShaderClientId
= 2001;
942 const GLuint kFShaderClientId
= 2002;
943 const GLuint kVShaderServiceId
= 3001;
944 const GLuint kFShaderServiceId
= 3002;
945 Shader
* vshader
= shader_manager_
.CreateShader(
946 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
947 ASSERT_TRUE(vshader
!= NULL
);
948 TestHelper::SetShaderStates(gl_
.get(), vshader
, true);
949 Shader
* fshader
= shader_manager_
.CreateShader(
950 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
951 ASSERT_TRUE(fshader
!= NULL
);
952 TestHelper::SetShaderStates(gl_
.get(), fshader
, true);
953 EXPECT_FALSE(vshader
->InUse());
954 EXPECT_FALSE(fshader
->InUse());
955 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
956 EXPECT_TRUE(vshader
->InUse());
957 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
958 EXPECT_TRUE(fshader
->InUse());
959 EXPECT_TRUE(program
->CanLink());
960 EXPECT_FALSE(program
->InUse());
961 EXPECT_FALSE(program
->IsDeleted());
962 manager_
.UseProgram(program
);
963 EXPECT_TRUE(program
->InUse());
964 manager_
.UseProgram(program
);
965 EXPECT_TRUE(program
->InUse());
966 manager_
.UnuseProgram(&shader_manager_
, program
);
967 EXPECT_TRUE(program
->InUse());
968 manager_
.UnuseProgram(&shader_manager_
, program
);
969 EXPECT_FALSE(program
->InUse());
970 Program
* info2
= manager_
.GetProgram(kClientProgramId
);
971 EXPECT_EQ(program
, info2
);
972 // this should delete the program.
973 EXPECT_CALL(*gl_
, DeleteProgram(kServiceProgramId
))
975 .RetiresOnSaturation();
976 manager_
.MarkAsDeleted(&shader_manager_
, program
);
977 info2
= manager_
.GetProgram(kClientProgramId
);
978 EXPECT_TRUE(info2
== NULL
);
979 EXPECT_FALSE(vshader
->InUse());
980 EXPECT_FALSE(fshader
->InUse());
983 TEST_F(ProgramManagerWithShaderTest
, ProgramInfoGetProgramInfo
) {
984 CommonDecoder::Bucket bucket
;
985 const Program
* program
= manager_
.GetProgram(kClientProgramId
);
986 ASSERT_TRUE(program
!= NULL
);
987 program
->GetProgramInfo(&manager_
, &bucket
);
988 ProgramInfoHeader
* header
=
989 bucket
.GetDataAs
<ProgramInfoHeader
*>(0, sizeof(ProgramInfoHeader
));
990 ASSERT_TRUE(header
!= NULL
);
991 EXPECT_EQ(1u, header
->link_status
);
992 EXPECT_EQ(arraysize(kAttribs
), header
->num_attribs
);
993 EXPECT_EQ(arraysize(kUniforms
), header
->num_uniforms
);
994 const ProgramInput
* inputs
= bucket
.GetDataAs
<const ProgramInput
*>(
996 sizeof(ProgramInput
) * (header
->num_attribs
+ header
->num_uniforms
));
997 ASSERT_TRUE(inputs
!= NULL
);
998 const ProgramInput
* input
= inputs
;
999 // TODO(gman): Don't assume these are in order.
1000 for (uint32 ii
= 0; ii
< header
->num_attribs
; ++ii
) {
1001 const AttribInfo
& expected
= kAttribs
[ii
];
1002 EXPECT_EQ(expected
.size
, input
->size
);
1003 EXPECT_EQ(expected
.type
, input
->type
);
1004 const int32
* location
= bucket
.GetDataAs
<const int32
*>(
1005 input
->location_offset
, sizeof(int32
));
1006 ASSERT_TRUE(location
!= NULL
);
1007 EXPECT_EQ(expected
.location
, *location
);
1008 const char* name_buf
= bucket
.GetDataAs
<const char*>(
1009 input
->name_offset
, input
->name_length
);
1010 ASSERT_TRUE(name_buf
!= NULL
);
1011 std::string
name(name_buf
, input
->name_length
);
1012 EXPECT_STREQ(expected
.name
, name
.c_str());
1015 // TODO(gman): Don't assume these are in order.
1016 for (uint32 ii
= 0; ii
< header
->num_uniforms
; ++ii
) {
1017 const UniformInfo
& expected
= kUniforms
[ii
];
1018 EXPECT_EQ(expected
.size
, input
->size
);
1019 EXPECT_EQ(expected
.type
, input
->type
);
1020 const int32
* locations
= bucket
.GetDataAs
<const int32
*>(
1021 input
->location_offset
, sizeof(int32
) * input
->size
);
1022 ASSERT_TRUE(locations
!= NULL
);
1023 for (int32 jj
= 0; jj
< input
->size
; ++jj
) {
1025 ProgramManager::MakeFakeLocation(expected
.fake_location
, jj
),
1028 const char* name_buf
= bucket
.GetDataAs
<const char*>(
1029 input
->name_offset
, input
->name_length
);
1030 ASSERT_TRUE(name_buf
!= NULL
);
1031 std::string
name(name_buf
, input
->name_length
);
1032 EXPECT_STREQ(expected
.good_name
, name
.c_str());
1035 EXPECT_EQ(header
->num_attribs
+ header
->num_uniforms
,
1036 static_cast<uint32
>(input
- inputs
));
1039 // Some drivers optimize out unused uniform array elements, so their
1040 // location would be -1.
1041 TEST_F(ProgramManagerWithShaderTest
, UnusedUniformArrayElements
) {
1042 CommonDecoder::Bucket bucket
;
1043 const Program
* program
= manager_
.GetProgram(kClientProgramId
);
1044 ASSERT_TRUE(program
!= NULL
);
1045 // Emulate the situation that only the first element has a valid location.
1046 // TODO(zmo): Don't assume these are in order.
1047 for (size_t ii
= 0; ii
< arraysize(kUniforms
); ++ii
) {
1048 Program::UniformInfo
* uniform
= const_cast<Program::UniformInfo
*>(
1049 program
->GetUniformInfo(ii
));
1050 ASSERT_TRUE(uniform
!= NULL
);
1051 EXPECT_EQ(static_cast<size_t>(kUniforms
[ii
].size
),
1052 uniform
->element_locations
.size());
1053 for (GLsizei jj
= 1; jj
< uniform
->size
; ++jj
)
1054 uniform
->element_locations
[jj
] = -1;
1056 program
->GetProgramInfo(&manager_
, &bucket
);
1057 ProgramInfoHeader
* header
=
1058 bucket
.GetDataAs
<ProgramInfoHeader
*>(0, sizeof(ProgramInfoHeader
));
1059 ASSERT_TRUE(header
!= NULL
);
1060 EXPECT_EQ(1u, header
->link_status
);
1061 EXPECT_EQ(arraysize(kAttribs
), header
->num_attribs
);
1062 EXPECT_EQ(arraysize(kUniforms
), header
->num_uniforms
);
1063 const ProgramInput
* inputs
= bucket
.GetDataAs
<const ProgramInput
*>(
1065 sizeof(ProgramInput
) * (header
->num_attribs
+ header
->num_uniforms
));
1066 ASSERT_TRUE(inputs
!= NULL
);
1067 const ProgramInput
* input
= inputs
+ header
->num_attribs
;
1068 for (uint32 ii
= 0; ii
< header
->num_uniforms
; ++ii
) {
1069 const UniformInfo
& expected
= kUniforms
[ii
];
1070 EXPECT_EQ(expected
.size
, input
->size
);
1071 const int32
* locations
= bucket
.GetDataAs
<const int32
*>(
1072 input
->location_offset
, sizeof(int32
) * input
->size
);
1073 ASSERT_TRUE(locations
!= NULL
);
1075 ProgramManager::MakeFakeLocation(expected
.fake_location
, 0),
1077 for (int32 jj
= 1; jj
< input
->size
; ++jj
)
1078 EXPECT_EQ(-1, locations
[jj
]);
1083 TEST_F(ProgramManagerWithShaderTest
, BindAttribLocationConflicts
) {
1085 const GLuint kVShaderClientId
= 1;
1086 const GLuint kVShaderServiceId
= 11;
1087 const GLuint kFShaderClientId
= 2;
1088 const GLuint kFShaderServiceId
= 12;
1089 ShaderTranslator::VariableMap attrib_map
;
1090 for (uint32 ii
= 0; ii
< kNumAttribs
; ++ii
) {
1091 attrib_map
[kAttribs
[ii
].name
] = ShaderTranslatorInterface::VariableInfo(
1094 SH_PRECISION_MEDIUMP
,
1098 // Check we can create shader.
1099 Shader
* vshader
= shader_manager_
.CreateShader(
1100 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
1101 Shader
* fshader
= shader_manager_
.CreateShader(
1102 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
1103 // Check shader got created.
1104 ASSERT_TRUE(vshader
!= NULL
&& fshader
!= NULL
);
1106 TestHelper::SetShaderStates(
1107 gl_
.get(), vshader
, true, NULL
, NULL
, &attrib_map
, NULL
, NULL
, NULL
);
1108 // Check attrib infos got copied.
1109 for (ShaderTranslator::VariableMap::const_iterator it
= attrib_map
.begin();
1110 it
!= attrib_map
.end(); ++it
) {
1111 const Shader::VariableInfo
* variable_info
=
1112 vshader
->GetAttribInfo(it
->first
);
1113 ASSERT_TRUE(variable_info
!= NULL
);
1114 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
1115 EXPECT_EQ(it
->second
.size
, variable_info
->size
);
1116 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
1117 EXPECT_EQ(it
->second
.static_use
, variable_info
->static_use
);
1118 EXPECT_EQ(it
->second
.name
, variable_info
->name
);
1120 TestHelper::SetShaderStates(
1121 gl_
.get(), fshader
, true, NULL
, NULL
, &attrib_map
, NULL
, NULL
, NULL
);
1124 const GLuint kClientProgramId
= 6666;
1125 const GLuint kServiceProgramId
= 8888;
1127 manager_
.CreateProgram(kClientProgramId
, kServiceProgramId
);
1128 ASSERT_TRUE(program
!= NULL
);
1129 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
1130 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
1132 EXPECT_FALSE(program
->DetectAttribLocationBindingConflicts());
1133 EXPECT_TRUE(LinkAsExpected(program
, true));
1135 program
->SetAttribLocationBinding(kAttrib1Name
, 0);
1136 EXPECT_FALSE(program
->DetectAttribLocationBindingConflicts());
1137 EXPECT_TRUE(LinkAsExpected(program
, true));
1139 program
->SetAttribLocationBinding("xxx", 0);
1140 EXPECT_FALSE(program
->DetectAttribLocationBindingConflicts());
1141 EXPECT_TRUE(LinkAsExpected(program
, true));
1143 program
->SetAttribLocationBinding(kAttrib2Name
, 1);
1144 EXPECT_FALSE(program
->DetectAttribLocationBindingConflicts());
1145 EXPECT_TRUE(LinkAsExpected(program
, true));
1147 program
->SetAttribLocationBinding(kAttrib2Name
, 0);
1148 EXPECT_TRUE(program
->DetectAttribLocationBindingConflicts());
1149 EXPECT_TRUE(LinkAsExpected(program
, false));
1152 TEST_F(ProgramManagerWithShaderTest
, UniformsPrecisionMismatch
) {
1154 const GLuint kVShaderClientId
= 1;
1155 const GLuint kVShaderServiceId
= 11;
1156 const GLuint kFShaderClientId
= 2;
1157 const GLuint kFShaderServiceId
= 12;
1159 ShaderTranslator::VariableMap vertex_uniform_map
;
1160 vertex_uniform_map
["a"] = ShaderTranslator::VariableInfo(
1161 1, 3, SH_PRECISION_MEDIUMP
, 1, "a");
1162 ShaderTranslator::VariableMap frag_uniform_map
;
1163 frag_uniform_map
["a"] = ShaderTranslator::VariableInfo(
1164 1, 3, SH_PRECISION_LOWP
, 1, "a");
1166 // Check we can create shader.
1167 Shader
* vshader
= shader_manager_
.CreateShader(
1168 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
1169 Shader
* fshader
= shader_manager_
.CreateShader(
1170 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
1171 // Check shader got created.
1172 ASSERT_TRUE(vshader
!= NULL
&& fshader
!= NULL
);
1174 TestHelper::SetShaderStates(
1175 gl_
.get(), vshader
, true, NULL
, NULL
, NULL
,
1176 &vertex_uniform_map
, NULL
, NULL
);
1177 TestHelper::SetShaderStates(
1178 gl_
.get(), fshader
, true, NULL
, NULL
, NULL
,
1179 &frag_uniform_map
, NULL
, NULL
);
1182 const GLuint kClientProgramId
= 6666;
1183 const GLuint kServiceProgramId
= 8888;
1185 manager_
.CreateProgram(kClientProgramId
, kServiceProgramId
);
1186 ASSERT_TRUE(program
!= NULL
);
1187 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
1188 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
1190 std::string conflicting_name
;
1192 EXPECT_TRUE(program
->DetectUniformsMismatch(&conflicting_name
));
1193 EXPECT_EQ("a", conflicting_name
);
1194 EXPECT_TRUE(LinkAsExpected(program
, false));
1197 // If a varying has different type in the vertex and fragment
1198 // shader, linking should fail.
1199 TEST_F(ProgramManagerWithShaderTest
, VaryingTypeMismatch
) {
1200 const VarInfo kVertexVarying
=
1201 { GL_FLOAT_VEC3
, 1, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
};
1202 const VarInfo kFragmentVarying
=
1203 { GL_FLOAT_VEC4
, 1, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
};
1204 Program
* program
= SetupShaderVariableTest(
1205 &kVertexVarying
, 1, &kFragmentVarying
, 1);
1207 std::string conflicting_name
;
1209 EXPECT_TRUE(program
->DetectVaryingsMismatch(&conflicting_name
));
1210 EXPECT_EQ("a", conflicting_name
);
1211 EXPECT_TRUE(LinkAsExpected(program
, false));
1214 // If a varying has different array size in the vertex and fragment
1215 // shader, linking should fail.
1216 TEST_F(ProgramManagerWithShaderTest
, VaryingArraySizeMismatch
) {
1217 const VarInfo kVertexVarying
=
1218 { GL_FLOAT
, 2, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
};
1219 const VarInfo kFragmentVarying
=
1220 { GL_FLOAT
, 3, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
};
1221 Program
* program
= SetupShaderVariableTest(
1222 &kVertexVarying
, 1, &kFragmentVarying
, 1);
1224 std::string conflicting_name
;
1226 EXPECT_TRUE(program
->DetectVaryingsMismatch(&conflicting_name
));
1227 EXPECT_EQ("a", conflicting_name
);
1228 EXPECT_TRUE(LinkAsExpected(program
, false));
1231 // If a varying has different precision in the vertex and fragment
1232 // shader, linking should succeed.
1233 TEST_F(ProgramManagerWithShaderTest
, VaryingPrecisionMismatch
) {
1234 const VarInfo kVertexVarying
=
1235 { GL_FLOAT
, 2, SH_PRECISION_HIGHP
, 1, "a", kVarVarying
};
1236 const VarInfo kFragmentVarying
=
1237 { GL_FLOAT
, 2, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
};
1238 Program
* program
= SetupShaderVariableTest(
1239 &kVertexVarying
, 1, &kFragmentVarying
, 1);
1241 std::string conflicting_name
;
1243 EXPECT_FALSE(program
->DetectVaryingsMismatch(&conflicting_name
));
1244 EXPECT_TRUE(conflicting_name
.empty());
1245 EXPECT_TRUE(LinkAsExpected(program
, true));
1248 // If a varying is statically used in fragment shader but not
1249 // declared in vertex shader, link should fail.
1250 TEST_F(ProgramManagerWithShaderTest
, VaryingMissing
) {
1251 const VarInfo kFragmentVarying
=
1252 { GL_FLOAT
, 3, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
};
1253 Program
* program
= SetupShaderVariableTest(
1254 NULL
, 0, &kFragmentVarying
, 1);
1256 std::string conflicting_name
;
1258 EXPECT_TRUE(program
->DetectVaryingsMismatch(&conflicting_name
));
1259 EXPECT_EQ("a", conflicting_name
);
1260 EXPECT_TRUE(LinkAsExpected(program
, false));
1263 // If a varying is declared but not statically used in fragment
1264 // shader, even if it's not declared in vertex shader, link should
1266 TEST_F(ProgramManagerWithShaderTest
, InactiveVarying
) {
1267 const VarInfo kFragmentVarying
=
1268 { GL_FLOAT
, 3, SH_PRECISION_MEDIUMP
, 0, "a", kVarVarying
};
1269 Program
* program
= SetupShaderVariableTest(
1270 NULL
, 0, &kFragmentVarying
, 1);
1272 std::string conflicting_name
;
1274 EXPECT_FALSE(program
->DetectVaryingsMismatch(&conflicting_name
));
1275 EXPECT_TRUE(conflicting_name
.empty());
1276 EXPECT_TRUE(LinkAsExpected(program
, true));
1279 // Uniforms and attributes are both global variables, thus sharing
1280 // the same namespace. Any name conflicts should cause link
1282 TEST_F(ProgramManagerWithShaderTest
, AttribUniformNameConflict
) {
1283 const VarInfo kVertexAttribute
=
1284 { GL_FLOAT_VEC4
, 1, SH_PRECISION_MEDIUMP
, 1, "a", kVarAttribute
};
1285 const VarInfo kFragmentUniform
=
1286 { GL_FLOAT_VEC4
, 1, SH_PRECISION_MEDIUMP
, 1, "a", kVarUniform
};
1287 Program
* program
= SetupShaderVariableTest(
1288 &kVertexAttribute
, 1, &kFragmentUniform
, 1);
1290 std::string conflicting_name
;
1292 EXPECT_TRUE(program
->DetectGlobalNameConflicts(&conflicting_name
));
1293 EXPECT_EQ("a", conflicting_name
);
1294 EXPECT_TRUE(LinkAsExpected(program
, false));
1297 // Varyings go over 8 rows.
1298 TEST_F(ProgramManagerWithShaderTest
, TooManyVaryings
) {
1299 const VarInfo kVertexVaryings
[] = {
1300 { GL_FLOAT_VEC4
, 4, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
},
1301 { GL_FLOAT_VEC4
, 5, SH_PRECISION_MEDIUMP
, 1, "b", kVarVarying
}
1303 const VarInfo kFragmentVaryings
[] = {
1304 { GL_FLOAT_VEC4
, 4, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
},
1305 { GL_FLOAT_VEC4
, 5, SH_PRECISION_MEDIUMP
, 1, "b", kVarVarying
}
1307 Program
* program
= SetupShaderVariableTest(
1308 kVertexVaryings
, 2, kFragmentVaryings
, 2);
1311 program
->CheckVaryingsPacking(Program::kCountOnlyStaticallyUsed
));
1312 EXPECT_TRUE(LinkAsExpected(program
, false));
1315 // Varyings go over 8 rows but some are inactive
1316 TEST_F(ProgramManagerWithShaderTest
, TooManyInactiveVaryings
) {
1317 const VarInfo kVertexVaryings
[] = {
1318 { GL_FLOAT_VEC4
, 4, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
},
1319 { GL_FLOAT_VEC4
, 5, SH_PRECISION_MEDIUMP
, 1, "b", kVarVarying
}
1321 const VarInfo kFragmentVaryings
[] = {
1322 { GL_FLOAT_VEC4
, 4, SH_PRECISION_MEDIUMP
, 0, "a", kVarVarying
},
1323 { GL_FLOAT_VEC4
, 5, SH_PRECISION_MEDIUMP
, 1, "b", kVarVarying
}
1325 Program
* program
= SetupShaderVariableTest(
1326 kVertexVaryings
, 2, kFragmentVaryings
, 2);
1329 program
->CheckVaryingsPacking(Program::kCountOnlyStaticallyUsed
));
1330 EXPECT_TRUE(LinkAsExpected(program
, true));
1333 // Varyings go over 8 rows but some are inactive.
1334 // However, we still fail the check if kCountAll option is used.
1335 TEST_F(ProgramManagerWithShaderTest
, CountAllVaryingsInPacking
) {
1336 const VarInfo kVertexVaryings
[] = {
1337 { GL_FLOAT_VEC4
, 4, SH_PRECISION_MEDIUMP
, 1, "a", kVarVarying
},
1338 { GL_FLOAT_VEC4
, 5, SH_PRECISION_MEDIUMP
, 1, "b", kVarVarying
}
1340 const VarInfo kFragmentVaryings
[] = {
1341 { GL_FLOAT_VEC4
, 4, SH_PRECISION_MEDIUMP
, 0, "a", kVarVarying
},
1342 { GL_FLOAT_VEC4
, 5, SH_PRECISION_MEDIUMP
, 1, "b", kVarVarying
}
1344 Program
* program
= SetupShaderVariableTest(
1345 kVertexVaryings
, 2, kFragmentVaryings
, 2);
1347 EXPECT_FALSE(program
->CheckVaryingsPacking(Program::kCountAll
));
1350 TEST_F(ProgramManagerWithShaderTest
, ClearWithSamplerTypes
) {
1351 const GLuint kVShaderClientId
= 2001;
1352 const GLuint kFShaderClientId
= 2002;
1353 const GLuint kVShaderServiceId
= 3001;
1354 const GLuint kFShaderServiceId
= 3002;
1355 Shader
* vshader
= shader_manager_
.CreateShader(
1356 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
1357 ASSERT_TRUE(vshader
!= NULL
);
1358 TestHelper::SetShaderStates(gl_
.get(), vshader
, true);
1359 Shader
* fshader
= shader_manager_
.CreateShader(
1360 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
1361 ASSERT_TRUE(fshader
!= NULL
);
1362 TestHelper::SetShaderStates(gl_
.get(), fshader
, true);
1363 static const GLuint kClientProgramId
= 1234;
1364 static const GLuint kServiceProgramId
= 5679;
1365 Program
* program
= manager_
.CreateProgram(
1366 kClientProgramId
, kServiceProgramId
);
1367 ASSERT_TRUE(program
!= NULL
);
1368 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
1369 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
1371 static const GLenum kSamplerTypes
[] = {
1374 GL_SAMPLER_EXTERNAL_OES
,
1376 GL_SAMPLER_2D_RECT_ARB
,
1378 const size_t kNumSamplerTypes
= arraysize(kSamplerTypes
);
1379 for (size_t ii
= 0; ii
< kNumSamplerTypes
; ++ii
) {
1380 static ProgramManagerWithShaderTest::AttribInfo kAttribs
[] = {
1381 { kAttrib1Name
, kAttrib1Size
, kAttrib1Type
, kAttrib1Location
, },
1382 { kAttrib2Name
, kAttrib2Size
, kAttrib2Type
, kAttrib2Location
, },
1383 { kAttrib3Name
, kAttrib3Size
, kAttrib3Type
, kAttrib3Location
, },
1385 ProgramManagerWithShaderTest::UniformInfo kUniforms
[] = {
1389 kUniform1FakeLocation
,
1390 kUniform1RealLocation
,
1391 kUniform1DesiredLocation
,
1397 kUniform2FakeLocation
,
1398 kUniform2RealLocation
,
1399 kUniform2DesiredLocation
,
1405 kUniform3FakeLocation
,
1406 kUniform3RealLocation
,
1407 kUniform3DesiredLocation
,
1411 const size_t kNumAttribs
= arraysize(kAttribs
);
1412 const size_t kNumUniforms
= arraysize(kUniforms
);
1413 SetupShader(kAttribs
, kNumAttribs
, kUniforms
, kNumUniforms
,
1415 program
->Link(NULL
, NULL
, NULL
, Program::kCountOnlyStaticallyUsed
,
1416 base::Bind(&ShaderCacheCb
));
1417 SetupExpectationsForClearingUniforms(kUniforms
, kNumUniforms
);
1418 manager_
.ClearUniforms(program
);
1422 TEST_F(ProgramManagerWithShaderTest
, BindUniformLocation
) {
1423 const GLuint kVShaderClientId
= 2001;
1424 const GLuint kFShaderClientId
= 2002;
1425 const GLuint kVShaderServiceId
= 3001;
1426 const GLuint kFShaderServiceId
= 3002;
1428 const GLint kUniform1DesiredLocation
= 10;
1429 const GLint kUniform2DesiredLocation
= -1;
1430 const GLint kUniform3DesiredLocation
= 5;
1432 Shader
* vshader
= shader_manager_
.CreateShader(
1433 kVShaderClientId
, kVShaderServiceId
, GL_VERTEX_SHADER
);
1434 ASSERT_TRUE(vshader
!= NULL
);
1435 TestHelper::SetShaderStates(gl_
.get(), vshader
, true);
1436 Shader
* fshader
= shader_manager_
.CreateShader(
1437 kFShaderClientId
, kFShaderServiceId
, GL_FRAGMENT_SHADER
);
1438 ASSERT_TRUE(fshader
!= NULL
);
1439 TestHelper::SetShaderStates(gl_
.get(), fshader
, true);
1440 static const GLuint kClientProgramId
= 1234;
1441 static const GLuint kServiceProgramId
= 5679;
1442 Program
* program
= manager_
.CreateProgram(
1443 kClientProgramId
, kServiceProgramId
);
1444 ASSERT_TRUE(program
!= NULL
);
1445 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, vshader
));
1446 EXPECT_TRUE(program
->AttachShader(&shader_manager_
, fshader
));
1447 EXPECT_TRUE(program
->SetUniformLocationBinding(
1448 kUniform1Name
, kUniform1DesiredLocation
));
1449 EXPECT_TRUE(program
->SetUniformLocationBinding(
1450 kUniform3BadName
, kUniform3DesiredLocation
));
1452 static ProgramManagerWithShaderTest::AttribInfo kAttribs
[] = {
1453 { kAttrib1Name
, kAttrib1Size
, kAttrib1Type
, kAttrib1Location
, },
1454 { kAttrib2Name
, kAttrib2Size
, kAttrib2Type
, kAttrib2Location
, },
1455 { kAttrib3Name
, kAttrib3Size
, kAttrib3Type
, kAttrib3Location
, },
1457 ProgramManagerWithShaderTest::UniformInfo kUniforms
[] = {
1461 kUniform1FakeLocation
,
1462 kUniform1RealLocation
,
1463 kUniform1DesiredLocation
,
1469 kUniform2FakeLocation
,
1470 kUniform2RealLocation
,
1471 kUniform2DesiredLocation
,
1477 kUniform3FakeLocation
,
1478 kUniform3RealLocation
,
1479 kUniform3DesiredLocation
,
1484 const size_t kNumAttribs
= arraysize(kAttribs
);
1485 const size_t kNumUniforms
= arraysize(kUniforms
);
1486 SetupShader(kAttribs
, kNumAttribs
, kUniforms
, kNumUniforms
,
1488 program
->Link(NULL
, NULL
, NULL
, Program::kCountOnlyStaticallyUsed
,
1489 base::Bind(&ShaderCacheCb
));
1491 EXPECT_EQ(kUniform1DesiredLocation
,
1492 program
->GetUniformFakeLocation(kUniform1Name
));
1493 EXPECT_EQ(kUniform3DesiredLocation
,
1494 program
->GetUniformFakeLocation(kUniform3BadName
));
1495 EXPECT_EQ(kUniform3DesiredLocation
,
1496 program
->GetUniformFakeLocation(kUniform3GoodName
));
1499 class ProgramManagerWithCacheTest
: public GpuServiceTest
{
1501 static const GLuint kClientProgramId
= 1;
1502 static const GLuint kServiceProgramId
= 10;
1503 static const GLuint kVertexShaderClientId
= 2;
1504 static const GLuint kFragmentShaderClientId
= 20;
1505 static const GLuint kVertexShaderServiceId
= 3;
1506 static const GLuint kFragmentShaderServiceId
= 30;
1508 ProgramManagerWithCacheTest()
1509 : cache_(new MockProgramCache()),
1510 manager_(cache_
.get(), kMaxVaryingVectors
),
1511 vertex_shader_(NULL
),
1512 fragment_shader_(NULL
),
1515 virtual ~ProgramManagerWithCacheTest() {
1516 manager_
.Destroy(false);
1517 shader_manager_
.Destroy(false);
1521 virtual void SetUp() {
1522 GpuServiceTest::SetUp();
1524 vertex_shader_
= shader_manager_
.CreateShader(
1525 kVertexShaderClientId
, kVertexShaderServiceId
, GL_VERTEX_SHADER
);
1526 fragment_shader_
= shader_manager_
.CreateShader(
1527 kFragmentShaderClientId
, kFragmentShaderServiceId
, GL_FRAGMENT_SHADER
);
1528 ASSERT_TRUE(vertex_shader_
!= NULL
);
1529 ASSERT_TRUE(fragment_shader_
!= NULL
);
1530 vertex_shader_
->set_source("lka asjf bjajsdfj");
1531 fragment_shader_
->set_source("lka asjf a fasgag 3rdsf3 bjajsdfj");
1533 program_
= manager_
.CreateProgram(
1534 kClientProgramId
, kServiceProgramId
);
1535 ASSERT_TRUE(program_
!= NULL
);
1537 program_
->AttachShader(&shader_manager_
, vertex_shader_
);
1538 program_
->AttachShader(&shader_manager_
, fragment_shader_
);
1541 void SetShadersCompiled() {
1542 TestHelper::SetShaderStates(gl_
.get(), vertex_shader_
, true);
1543 TestHelper::SetShaderStates(gl_
.get(), fragment_shader_
, true);
1546 void SetProgramCached() {
1547 cache_
->LinkedProgramCacheSuccess(
1548 vertex_shader_
->source(),
1550 fragment_shader_
->source(),
1552 &program_
->bind_attrib_location_map());
1555 void SetExpectationsForProgramCached() {
1556 SetExpectationsForProgramCached(program_
,
1561 void SetExpectationsForProgramCached(
1563 Shader
* vertex_shader
,
1564 Shader
* fragment_shader
) {
1565 EXPECT_CALL(*cache_
.get(), SaveLinkedProgram(
1566 program
->service_id(),
1571 &program
->bind_attrib_location_map(),
1575 void SetExpectationsForNotCachingProgram() {
1576 SetExpectationsForNotCachingProgram(program_
,
1581 void SetExpectationsForNotCachingProgram(
1583 Shader
* vertex_shader
,
1584 Shader
* fragment_shader
) {
1585 EXPECT_CALL(*cache_
.get(), SaveLinkedProgram(
1586 program
->service_id(),
1591 &program
->bind_attrib_location_map(),
1595 void SetExpectationsForProgramLoad(ProgramCache::ProgramLoadResult result
) {
1596 SetExpectationsForProgramLoad(kServiceProgramId
,
1603 void SetExpectationsForProgramLoad(
1604 GLuint service_program_id
,
1606 Shader
* vertex_shader
,
1607 Shader
* fragment_shader
,
1608 ProgramCache::ProgramLoadResult result
) {
1609 EXPECT_CALL(*cache_
.get(),
1610 LoadLinkedProgram(service_program_id
,
1615 &program
->bind_attrib_location_map(),
1617 .WillOnce(Return(result
));
1620 void SetExpectationsForProgramLoadSuccess() {
1621 SetExpectationsForProgramLoadSuccess(kServiceProgramId
);
1624 void SetExpectationsForProgramLoadSuccess(GLuint service_program_id
) {
1625 TestHelper::SetupProgramSuccessExpectations(gl_
.get(),
1630 service_program_id
);
1633 void SetExpectationsForProgramLink() {
1634 SetExpectationsForProgramLink(kServiceProgramId
);
1637 void SetExpectationsForProgramLink(GLuint service_program_id
) {
1638 TestHelper::SetupShader(gl_
.get(), NULL
, 0, NULL
, 0, service_program_id
);
1639 if (gfx::g_driver_gl
.ext
.b_GL_ARB_get_program_binary
) {
1640 EXPECT_CALL(*gl_
.get(),
1641 ProgramParameteri(service_program_id
,
1642 PROGRAM_BINARY_RETRIEVABLE_HINT
,
1647 void SetExpectationsForSuccessCompile(
1648 const Shader
* shader
) {
1649 const GLuint shader_id
= shader
->service_id();
1650 const char* src
= shader
->source().c_str();
1651 EXPECT_CALL(*gl_
.get(),
1652 ShaderSource(shader_id
, 1, Pointee(src
), NULL
)).Times(1);
1653 EXPECT_CALL(*gl_
.get(), CompileShader(shader_id
)).Times(1);
1654 EXPECT_CALL(*gl_
.get(), GetShaderiv(shader_id
, GL_COMPILE_STATUS
, _
))
1655 .WillOnce(SetArgumentPointee
<2>(GL_TRUE
));
1658 void SetExpectationsForNoCompile(const Shader
* shader
) {
1659 const GLuint shader_id
= shader
->service_id();
1660 const char* src
= shader
->source().c_str();
1661 EXPECT_CALL(*gl_
.get(),
1662 ShaderSource(shader_id
, 1, Pointee(src
), NULL
)).Times(0);
1663 EXPECT_CALL(*gl_
.get(), CompileShader(shader_id
)).Times(0);
1664 EXPECT_CALL(*gl_
.get(), GetShaderiv(shader_id
, GL_COMPILE_STATUS
, _
))
1668 void SetExpectationsForErrorCompile(const Shader
* shader
) {
1669 const GLuint shader_id
= shader
->service_id();
1670 const char* src
= shader
->source().c_str();
1671 EXPECT_CALL(*gl_
.get(),
1672 ShaderSource(shader_id
, 1, Pointee(src
), NULL
)).Times(1);
1673 EXPECT_CALL(*gl_
.get(), CompileShader(shader_id
)).Times(1);
1674 EXPECT_CALL(*gl_
.get(), GetShaderiv(shader_id
, GL_COMPILE_STATUS
, _
))
1675 .WillOnce(SetArgumentPointee
<2>(GL_FALSE
));
1676 EXPECT_CALL(*gl_
.get(), GetShaderiv(shader_id
, GL_INFO_LOG_LENGTH
, _
))
1677 .WillOnce(SetArgumentPointee
<2>(0));
1678 EXPECT_CALL(*gl_
.get(), GetShaderInfoLog(shader_id
, 0, _
, _
))
1682 scoped_ptr
<MockProgramCache
> cache_
;
1683 ProgramManager manager_
;
1685 Shader
* vertex_shader_
;
1686 Shader
* fragment_shader_
;
1688 ShaderManager shader_manager_
;
1691 // GCC requires these declarations, but MSVC requires they not be present
1692 #ifndef COMPILER_MSVC
1693 const GLuint
ProgramManagerWithCacheTest::kClientProgramId
;
1694 const GLuint
ProgramManagerWithCacheTest::kServiceProgramId
;
1695 const GLuint
ProgramManagerWithCacheTest::kVertexShaderClientId
;
1696 const GLuint
ProgramManagerWithCacheTest::kFragmentShaderClientId
;
1697 const GLuint
ProgramManagerWithCacheTest::kVertexShaderServiceId
;
1698 const GLuint
ProgramManagerWithCacheTest::kFragmentShaderServiceId
;
1701 TEST_F(ProgramManagerWithCacheTest
, CacheProgramOnSuccessfulLink
) {
1702 SetShadersCompiled();
1703 SetExpectationsForProgramLink();
1704 SetExpectationsForProgramCached();
1705 EXPECT_TRUE(program_
->Link(NULL
, NULL
, NULL
,
1706 Program::kCountOnlyStaticallyUsed
, base::Bind(&ShaderCacheCb
)));
1709 TEST_F(ProgramManagerWithCacheTest
, LoadProgramOnProgramCacheHit
) {
1710 SetShadersCompiled();
1713 SetExpectationsForNoCompile(vertex_shader_
);
1714 SetExpectationsForNoCompile(fragment_shader_
);
1715 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS
);
1716 SetExpectationsForNotCachingProgram();
1717 SetExpectationsForProgramLoadSuccess();
1719 EXPECT_TRUE(program_
->Link(NULL
, NULL
, NULL
,
1720 Program::kCountOnlyStaticallyUsed
, base::Bind(&ShaderCacheCb
)));
1723 } // namespace gles2