program_manager.h revision bb1529ce867d8845a77ec7cdf3e3003ef1771a40
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
20namespace gpu {
21namespace gles2 {
22
23class FeatureInfo;
24class ProgramCache;
25class ProgramManager;
26class Shader;
27class ShaderManager;
28class 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.
33class 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.
321class 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