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 | #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" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 16 | #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 17 | #include "gpu/command_buffer/service/shader_manager.h" |
| 18 | #include "gpu/gpu_export.h" |
| 19 | |
| 20 | namespace gpu { |
| 21 | namespace gles2 { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 22 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 23 | class FeatureInfo; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 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 | }; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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: |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 323 | explicit ProgramManager(ProgramCache* program_cache); |
| 324 | ~ProgramManager(); |
| 325 | |
| 326 | // Must call before destruction. |
| 327 | void Destroy(bool have_context); |
| 328 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 329 | // Creates a new program. |
| 330 | Program* CreateProgram(GLuint client_id, GLuint service_id); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 331 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 332 | // Gets a program. |
| 333 | Program* GetProgram(GLuint client_id); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 341 | // Marks a program as deleted. If it is not used the program will be deleted. |
| 342 | void MarkAsDeleted(ShaderManager* shader_manager, Program* program); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 343 | |
| 344 | // Marks a program as used. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 345 | void UseProgram(Program* program); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 346 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 347 | // Makes a program as unused. If deleted the program will be removed. |
| 348 | void UnuseProgram(ShaderManager* shader_manager, Program* program); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 349 | |
| 350 | // Clears the uniforms for this program. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 351 | void ClearUniforms(Program* program); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 352 | |
| 353 | // Returns true if prefix is invalid for gl. |
| 354 | static bool IsInvalidPrefix(const char* name, size_t length); |
| 355 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 356 | // Check if a Program is owned by this ProgramManager. |
| 357 | bool IsOwned(Program* program); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 358 | |
| 359 | static int32 MakeFakeLocation(int32 index, int32 element); |
| 360 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 361 | void DoCompileShader(Shader* shader, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 362 | ShaderTranslator* translator, |
| 363 | FeatureInfo* feature_info); |
| 364 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 365 | private: |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 366 | friend class Program; |
| 367 | |
| 368 | void StartTracking(Program* program); |
| 369 | void StopTracking(Program* program); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 370 | |
| 371 | // Info for each "successfully linked" program by service side program Id. |
| 372 | // TODO(gman): Choose a faster container. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 373 | typedef std::map<GLuint, scoped_refptr<Program> > ProgramMap; |
| 374 | ProgramMap programs_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 375 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 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_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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( |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 390 | ShaderManager* shader_manager, Program* program); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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_ |