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