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