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