Home | History | Annotate | Download | only in service
      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