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