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 #ifndef GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_ 6 #define GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 #include "base/basictypes.h" 12 #include "base/logging.h" 13 #include "base/memory/ref_counted.h" 14 #include "gpu/command_buffer/service/common_decoder.h" 15 #include "gpu/command_buffer/service/gl_utils.h" 16 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 17 #include "gpu/command_buffer/service/shader_manager.h" 18 #include "gpu/gpu_export.h" 19 20 namespace gpu { 21 namespace gles2 { 22 23 class ProgramCache; 24 class ProgramManager; 25 class Shader; 26 class ShaderManager; 27 class ShaderTranslator; 28 29 // This is used to track which attributes a particular program needs 30 // so we can verify at glDrawXXX time that every attribute is either disabled 31 // or if enabled that it points to a valid source. 32 class GPU_EXPORT Program : public base::RefCounted<Program> { 33 public: 34 static const int kMaxAttachedShaders = 2; 35 36 enum VaryingsPackingOption { 37 kCountOnlyStaticallyUsed, 38 kCountAll 39 }; 40 41 enum UniformApiType { 42 kUniform1i = 1 << 0, 43 kUniform2i = 1 << 1, 44 kUniform3i = 1 << 2, 45 kUniform4i = 1 << 3, 46 kUniform1f = 1 << 4, 47 kUniform2f = 1 << 5, 48 kUniform3f = 1 << 6, 49 kUniform4f = 1 << 7, 50 kUniformMatrix2f = 1 << 8, 51 kUniformMatrix3f = 1 << 9, 52 kUniformMatrix4f = 1 << 10, 53 }; 54 55 struct UniformInfo { 56 UniformInfo(); 57 UniformInfo( 58 GLsizei _size, GLenum _type, GLint _fake_location_base, 59 const std::string& _name); 60 ~UniformInfo(); 61 62 bool IsValid() const { 63 return size != 0; 64 } 65 66 bool IsSampler() const { 67 return type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB || 68 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES; 69 } 70 71 GLsizei size; 72 GLenum type; 73 uint32 accepts_api_type; 74 GLint fake_location_base; 75 bool is_array; 76 std::string name; 77 std::vector<GLint> element_locations; 78 std::vector<GLuint> texture_units; 79 }; 80 struct VertexAttrib { 81 VertexAttrib(GLsizei _size, GLenum _type, const std::string& _name, 82 GLint _location) 83 : size(_size), 84 type(_type), 85 location(_location), 86 name(_name) { 87 } 88 GLsizei size; 89 GLenum type; 90 GLint location; 91 std::string name; 92 }; 93 94 typedef std::vector<UniformInfo> UniformInfoVector; 95 typedef std::vector<VertexAttrib> AttribInfoVector; 96 typedef std::vector<int> SamplerIndices; 97 typedef std::map<std::string, GLint> LocationMap; 98 99 Program(ProgramManager* manager, GLuint service_id); 100 101 GLuint service_id() const { 102 return service_id_; 103 } 104 105 const SamplerIndices& sampler_indices() { 106 return sampler_indices_; 107 } 108 109 const AttribInfoVector& GetAttribInfos() const { 110 return attrib_infos_; 111 } 112 113 const VertexAttrib* GetAttribInfo(GLint index) const { 114 return (static_cast<size_t>(index) < attrib_infos_.size()) ? 115 &attrib_infos_[index] : NULL; 116 } 117 118 GLint GetAttribLocation(const std::string& name) const; 119 120 const VertexAttrib* GetAttribInfoByLocation(GLuint location) const { 121 if (location < attrib_location_to_index_map_.size()) { 122 GLint index = attrib_location_to_index_map_[location]; 123 if (index >= 0) { 124 return &attrib_infos_[index]; 125 } 126 } 127 return NULL; 128 } 129 130 const UniformInfo* GetUniformInfo(GLint index) const; 131 132 // If the original name is not found, return NULL. 133 const std::string* GetAttribMappedName( 134 const std::string& original_name) const; 135 136 // If the hashed name is not found, return NULL. 137 const std::string* GetOriginalNameFromHashedName( 138 const std::string& hashed_name) const; 139 140 // Gets the fake location of a uniform by name. 141 GLint GetUniformFakeLocation(const std::string& name) const; 142 143 // Gets the UniformInfo of a uniform by location. 144 const UniformInfo* GetUniformInfoByFakeLocation( 145 GLint fake_location, GLint* real_location, GLint* array_index) const; 146 147 // Gets all the program info. 148 void GetProgramInfo( 149 ProgramManager* manager, CommonDecoder::Bucket* bucket) const; 150 151 // Sets the sampler values for a uniform. 152 // This is safe to call for any location. If the location is not 153 // a sampler uniform nothing will happen. 154 // Returns false if fake_location is a sampler and any value 155 // is >= num_texture_units. Returns true otherwise. 156 bool SetSamplers( 157 GLint num_texture_units, GLint fake_location, 158 GLsizei count, const GLint* value); 159 160 bool IsDeleted() const { 161 return deleted_; 162 } 163 164 void GetProgramiv(GLenum pname, GLint* params); 165 166 bool IsValid() const { 167 return valid_; 168 } 169 170 bool AttachShader(ShaderManager* manager, Shader* shader); 171 bool DetachShader(ShaderManager* manager, Shader* shader); 172 173 bool CanLink() const; 174 175 // Performs glLinkProgram and related activities. 176 bool Link(ShaderManager* manager, 177 ShaderTranslator* vertex_translator, 178 ShaderTranslator* fragment_shader, 179 VaryingsPackingOption varyings_packing_option, 180 const ShaderCacheCallback& shader_callback); 181 182 // Performs glValidateProgram and related activities. 183 void Validate(); 184 185 const std::string* log_info() const { 186 return log_info_.get(); 187 } 188 189 bool InUse() const { 190 DCHECK_GE(use_count_, 0); 191 return use_count_ != 0; 192 } 193 194 // Sets attribute-location binding from a glBindAttribLocation() call. 195 void SetAttribLocationBinding(const std::string& attrib, GLint location) { 196 bind_attrib_location_map_[attrib] = location; 197 } 198 199 // Sets uniform-location binding from a glBindUniformLocationCHROMIUM call. 200 // returns false if error. 201 bool SetUniformLocationBinding(const std::string& name, GLint location); 202 203 // Detects if there are attribute location conflicts from 204 // glBindAttribLocation() calls. 205 // We only consider the declared attributes in the program. 206 bool DetectAttribLocationBindingConflicts() const; 207 208 // Detects if there are uniforms of the same name but different type 209 // or precision in vertex/fragment shaders. 210 // Return true and set the first found conflicting hashed name to 211 // conflicting_name if such cases are detected. 212 bool DetectUniformsMismatch(std::string* conflicting_name) const; 213 214 // Return true if a varying is statically used in fragment shader, but it 215 // is not declared in vertex shader. 216 bool DetectVaryingsMismatch(std::string* conflicting_name) const; 217 218 // Return true if an uniform and an attribute share the same name. 219 bool DetectGlobalNameConflicts(std::string* conflicting_name) const; 220 221 // Return false if varyings can't be packed into the max available 222 // varying registers. 223 bool CheckVaryingsPacking(VaryingsPackingOption option) const; 224 225 // Visible for testing 226 const LocationMap& bind_attrib_location_map() const { 227 return bind_attrib_location_map_; 228 } 229 230 private: 231 friend class base::RefCounted<Program>; 232 friend class ProgramManager; 233 234 ~Program(); 235 236 void set_log_info(const char* str) { 237 log_info_.reset(str ? new std::string(str) : NULL); 238 } 239 240 void ClearLinkStatus() { 241 link_status_ = false; 242 } 243 244 void IncUseCount() { 245 ++use_count_; 246 } 247 248 void DecUseCount() { 249 --use_count_; 250 DCHECK_GE(use_count_, 0); 251 } 252 253 void MarkAsDeleted() { 254 DCHECK(!deleted_); 255 deleted_ = true; 256 } 257 258 // Resets the program. 259 void Reset(); 260 261 // Updates the program info after a successful link. 262 void Update(); 263 264 // Process the program log, replacing the hashed names with original names. 265 std::string ProcessLogInfo(const std::string& log); 266 267 // Updates the program log info from GL 268 void UpdateLogInfo(); 269 270 // Clears all the uniforms. 271 void ClearUniforms(std::vector<uint8>* zero_buffer); 272 273 // If long attribate names are mapped during shader translation, call 274 // glBindAttribLocation() again with the mapped names. 275 // This is called right before the glLink() call, but after shaders are 276 // translated. 277 void ExecuteBindAttribLocationCalls(); 278 279 bool AddUniformInfo( 280 GLsizei size, GLenum type, GLint location, GLint fake_base_location, 281 const std::string& name, const std::string& original_name, 282 size_t* next_available_index); 283 284 void GetCorrectedVariableInfo( 285 bool use_uniforms, const std::string& name, std::string* corrected_name, 286 std::string* original_name, GLsizei* size, GLenum* type) const; 287 288 void DetachShaders(ShaderManager* manager); 289 290 static inline GLint GetUniformInfoIndexFromFakeLocation( 291 GLint fake_location) { 292 return fake_location & 0xFFFF; 293 } 294 295 static inline GLint GetArrayElementIndexFromFakeLocation( 296 GLint fake_location) { 297 return (fake_location >> 16) & 0xFFFF; 298 } 299 300 ProgramManager* manager_; 301 302 int use_count_; 303 304 GLsizei max_attrib_name_length_; 305 306 // Attrib by index. 307 AttribInfoVector attrib_infos_; 308 309 // Attrib by location to index. 310 std::vector<GLint> attrib_location_to_index_map_; 311 312 GLsizei max_uniform_name_length_; 313 314 // Uniform info by index. 315 UniformInfoVector uniform_infos_; 316 317 // The indices of the uniforms that are samplers. 318 SamplerIndices sampler_indices_; 319 320 // The program this Program is tracking. 321 GLuint service_id_; 322 323 // Shaders by type of shader. 324 scoped_refptr<Shader> 325 attached_shaders_[kMaxAttachedShaders]; 326 327 // True if this program is marked as deleted. 328 bool deleted_; 329 330 // This is true if glLinkProgram was successful at least once. 331 bool valid_; 332 333 // This is true if glLinkProgram was successful last time it was called. 334 bool link_status_; 335 336 // True if the uniforms have been cleared. 337 bool uniforms_cleared_; 338 339 // This is different than uniform_infos_.size() because 340 // that is a sparce array. 341 GLint num_uniforms_; 342 343 // Log info 344 scoped_ptr<std::string> log_info_; 345 346 // attribute-location binding map from glBindAttribLocation() calls. 347 LocationMap bind_attrib_location_map_; 348 349 // uniform-location binding map from glBindUniformLocationCHROMIUM() calls. 350 LocationMap bind_uniform_location_map_; 351 }; 352 353 // Tracks the Programs. 354 // 355 // NOTE: To support shared resources an instance of this class will 356 // need to be shared by multiple GLES2Decoders. 357 class GPU_EXPORT ProgramManager { 358 public: 359 explicit ProgramManager(ProgramCache* program_cache, 360 uint32 max_varying_vectors); 361 ~ProgramManager(); 362 363 // Must call before destruction. 364 void Destroy(bool have_context); 365 366 // Creates a new program. 367 Program* CreateProgram(GLuint client_id, GLuint service_id); 368 369 // Gets a program. 370 Program* GetProgram(GLuint client_id); 371 372 // Gets a client id for a given service id. 373 bool GetClientId(GLuint service_id, GLuint* client_id) const; 374 375 // Gets the shader cache 376 ProgramCache* program_cache() const; 377 378 // Marks a program as deleted. If it is not used the program will be deleted. 379 void MarkAsDeleted(ShaderManager* shader_manager, Program* program); 380 381 // Marks a program as used. 382 void UseProgram(Program* program); 383 384 // Makes a program as unused. If deleted the program will be removed. 385 void UnuseProgram(ShaderManager* shader_manager, Program* program); 386 387 // Clears the uniforms for this program. 388 void ClearUniforms(Program* program); 389 390 // Returns true if prefix is invalid for gl. 391 static bool IsInvalidPrefix(const char* name, size_t length); 392 393 // Check if a Program is owned by this ProgramManager. 394 bool IsOwned(Program* program); 395 396 static int32 MakeFakeLocation(int32 index, int32 element); 397 398 uint32 max_varying_vectors() const { 399 return max_varying_vectors_; 400 } 401 402 private: 403 friend class Program; 404 405 void StartTracking(Program* program); 406 void StopTracking(Program* program); 407 408 void RemoveProgramInfoIfUnused( 409 ShaderManager* shader_manager, Program* program); 410 411 // Info for each "successfully linked" program by service side program Id. 412 // TODO(gman): Choose a faster container. 413 typedef std::map<GLuint, scoped_refptr<Program> > ProgramMap; 414 ProgramMap programs_; 415 416 // Counts the number of Program allocated with 'this' as its manager. 417 // Allows to check no Program will outlive this. 418 unsigned int program_count_; 419 420 bool have_context_; 421 422 // Used to clear uniforms. 423 std::vector<uint8> zero_; 424 425 ProgramCache* program_cache_; 426 427 uint32 max_varying_vectors_; 428 429 DISALLOW_COPY_AND_ASSIGN(ProgramManager); 430 }; 431 432 } // namespace gles2 433 } // namespace gpu 434 435 #endif // GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_ 436