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