• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IsValidUniformInfo62     bool IsValid() const {
63       return size != 0;
64     }
65 
IsSamplerUniformInfo66     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 {
VertexAttribVertexAttrib81     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 
service_id()101   GLuint service_id() const {
102     return service_id_;
103   }
104 
sampler_indices()105   const SamplerIndices& sampler_indices() {
106     return sampler_indices_;
107   }
108 
GetAttribInfos()109   const AttribInfoVector& GetAttribInfos() const {
110     return attrib_infos_;
111   }
112 
GetAttribInfo(GLint index)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 
GetAttribInfoByLocation(GLuint location)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 
IsDeleted()160   bool IsDeleted() const {
161     return deleted_;
162   }
163 
164   void GetProgramiv(GLenum pname, GLint* params);
165 
IsValid()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 
log_info()185   const std::string* log_info() const {
186     return log_info_.get();
187   }
188 
InUse()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.
SetAttribLocationBinding(const std::string & attrib,GLint location)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
bind_attrib_location_map()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 
set_log_info(const char * str)236   void set_log_info(const char* str) {
237     log_info_.reset(str ? new std::string(str) : NULL);
238   }
239 
ClearLinkStatus()240   void ClearLinkStatus() {
241     link_status_ = false;
242   }
243 
IncUseCount()244   void IncUseCount() {
245     ++use_count_;
246   }
247 
DecUseCount()248   void DecUseCount() {
249     --use_count_;
250     DCHECK_GE(use_count_, 0);
251   }
252 
MarkAsDeleted()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 
GetUniformInfoIndexFromFakeLocation(GLint fake_location)290   static inline GLint GetUniformInfoIndexFromFakeLocation(
291       GLint fake_location) {
292     return fake_location & 0xFFFF;
293   }
294 
GetArrayElementIndexFromFakeLocation(GLint fake_location)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   enum TranslatedShaderSourceType {
360     kANGLE,
361     kGL,  // GL or GLES
362   };
363 
364   explicit ProgramManager(ProgramCache* program_cache,
365                           uint32 max_varying_vectors);
366   ~ProgramManager();
367 
368   // Must call before destruction.
369   void Destroy(bool have_context);
370 
371   // Creates a new program.
372   Program* CreateProgram(GLuint client_id, GLuint service_id);
373 
374   // Gets a program.
375   Program* GetProgram(GLuint client_id);
376 
377   // Gets a client id for a given service id.
378   bool GetClientId(GLuint service_id, GLuint* client_id) const;
379 
380   // Gets the shader cache
381   ProgramCache* program_cache() const;
382 
383   // Marks a program as deleted. If it is not used the program will be deleted.
384   void MarkAsDeleted(ShaderManager* shader_manager, Program* program);
385 
386   // Marks a program as used.
387   void UseProgram(Program* program);
388 
389   // Makes a program as unused. If deleted the program will be removed.
390   void UnuseProgram(ShaderManager* shader_manager, Program* program);
391 
392   // Clears the uniforms for this program.
393   void ClearUniforms(Program* program);
394 
395   // Returns true if prefix is invalid for gl.
396   static bool IsInvalidPrefix(const char* name, size_t length);
397 
398   // Check if a Program is owned by this ProgramManager.
399   bool IsOwned(Program* program);
400 
401   static int32 MakeFakeLocation(int32 index, int32 element);
402 
403   void DoCompileShader(
404       Shader* shader,
405       ShaderTranslator* translator,
406       TranslatedShaderSourceType translated_shader_source_type);
407 
max_varying_vectors()408   uint32 max_varying_vectors() const {
409     return max_varying_vectors_;
410   }
411 
412  private:
413   friend class Program;
414 
415   void StartTracking(Program* program);
416   void StopTracking(Program* program);
417 
418   void RemoveProgramInfoIfUnused(
419       ShaderManager* shader_manager, Program* program);
420 
421   // Info for each "successfully linked" program by service side program Id.
422   // TODO(gman): Choose a faster container.
423   typedef std::map<GLuint, scoped_refptr<Program> > ProgramMap;
424   ProgramMap programs_;
425 
426   // Counts the number of Program allocated with 'this' as its manager.
427   // Allows to check no Program will outlive this.
428   unsigned int program_count_;
429 
430   bool have_context_;
431 
432   // Used to clear uniforms.
433   std::vector<uint8> zero_;
434 
435   ProgramCache* program_cache_;
436 
437   uint32 max_varying_vectors_;
438 
439   DISALLOW_COPY_AND_ASSIGN(ProgramManager);
440 };
441 
442 }  // namespace gles2
443 }  // namespace gpu
444 
445 #endif  // GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_
446