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