Elim cr-checkbox
[chromium-blink-merge.git] / gpu / command_buffer / service / program_manager.h
blob1df651955873efcd765d129ce591ec3304b1b01e
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.
5 #ifndef GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_
6 #define GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_
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"
20 namespace gpu {
21 namespace gles2 {
23 class ProgramCache;
24 class ProgramManager;
25 class Shader;
26 class ShaderManager;
28 // This is used to track which attributes a particular program needs
29 // so we can verify at glDrawXXX time that every attribute is either disabled
30 // or if enabled that it points to a valid source.
31 class GPU_EXPORT Program : public base::RefCounted<Program> {
32 public:
33 static const int kMaxAttachedShaders = 2;
35 enum VaryingsPackingOption {
36 kCountOnlyStaticallyUsed,
37 kCountAll
40 enum UniformApiType {
41 kUniformNone = 0,
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 kUniform1ui = 1 << 11,
54 kUniform2ui = 1 << 12,
55 kUniform3ui = 1 << 13,
56 kUniform4ui = 1 << 14,
57 kUniformMatrix2x3f = 1 << 15,
58 kUniformMatrix2x4f = 1 << 16,
59 kUniformMatrix3x2f = 1 << 17,
60 kUniformMatrix3x4f = 1 << 18,
61 kUniformMatrix4x2f = 1 << 19,
62 kUniformMatrix4x3f = 1 << 20,
65 struct UniformInfo {
66 UniformInfo();
67 UniformInfo(
68 GLsizei _size, GLenum _type, GLint _fake_location_base,
69 const std::string& _name);
70 ~UniformInfo();
72 bool IsValid() const {
73 return size != 0;
76 bool IsSampler() const {
77 return type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
78 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES;
81 GLsizei size;
82 GLenum type;
83 uint32 accepts_api_type;
84 GLint fake_location_base;
85 bool is_array;
86 std::string name;
87 std::vector<GLint> element_locations;
88 std::vector<GLuint> texture_units;
90 struct VertexAttrib {
91 VertexAttrib(GLsizei _size, GLenum _type, const std::string& _name,
92 GLint _location)
93 : size(_size),
94 type(_type),
95 location(_location),
96 name(_name) {
98 GLsizei size;
99 GLenum type;
100 GLint location;
101 std::string name;
104 typedef std::vector<UniformInfo> UniformInfoVector;
105 typedef std::vector<VertexAttrib> AttribInfoVector;
106 typedef std::vector<int> SamplerIndices;
107 typedef std::map<std::string, GLint> LocationMap;
108 typedef std::vector<std::string> StringVector;
110 Program(ProgramManager* manager, GLuint service_id);
112 GLuint service_id() const {
113 return service_id_;
116 const SamplerIndices& sampler_indices() {
117 return sampler_indices_;
120 const AttribInfoVector& GetAttribInfos() const {
121 return attrib_infos_;
124 const VertexAttrib* GetAttribInfo(GLint index) const {
125 return (static_cast<size_t>(index) < attrib_infos_.size()) ?
126 &attrib_infos_[index] : NULL;
129 GLint GetAttribLocation(const std::string& original_name) const;
131 const VertexAttrib* GetAttribInfoByLocation(GLuint location) const {
132 if (location < attrib_location_to_index_map_.size()) {
133 GLint index = attrib_location_to_index_map_[location];
134 if (index >= 0) {
135 return &attrib_infos_[index];
138 return NULL;
141 const UniformInfo* GetUniformInfo(GLint index) const;
143 // If the original name is not found, return NULL.
144 const std::string* GetAttribMappedName(
145 const std::string& original_name) const;
147 // If the original name is not found, return NULL.
148 const std::string* GetUniformMappedName(
149 const std::string& original_name) const;
151 // If the hashed name is not found, return NULL.
152 const std::string* GetOriginalNameFromHashedName(
153 const std::string& hashed_name) const;
155 // Gets the fake location of a uniform by name.
156 GLint GetUniformFakeLocation(const std::string& name) const;
158 // Gets the UniformInfo of a uniform by location.
159 const UniformInfo* GetUniformInfoByFakeLocation(
160 GLint fake_location, GLint* real_location, GLint* array_index) const;
162 // Gets all the program info.
163 void GetProgramInfo(
164 ProgramManager* manager, CommonDecoder::Bucket* bucket) const;
166 // Gets all the UniformBlock info.
167 // Return false on overflow.
168 bool GetUniformBlocks(CommonDecoder::Bucket* bucket) const;
170 // Gets all the TransformFeedbackVarying info.
171 // Return false on overflow.
172 bool GetTransformFeedbackVaryings(CommonDecoder::Bucket* bucket) const;
174 // Gather all info through glGetActiveUniformsiv, except for size, type,
175 // name_length, which we gather through glGetActiveUniform in
176 // glGetProgramInfoCHROMIUM.
177 bool GetUniformsES3(CommonDecoder::Bucket* bucket) const;
179 // Sets the sampler values for a uniform.
180 // This is safe to call for any location. If the location is not
181 // a sampler uniform nothing will happen.
182 // Returns false if fake_location is a sampler and any value
183 // is >= num_texture_units. Returns true otherwise.
184 bool SetSamplers(
185 GLint num_texture_units, GLint fake_location,
186 GLsizei count, const GLint* value);
188 bool IsDeleted() const {
189 return deleted_;
192 void GetProgramiv(GLenum pname, GLint* params);
194 bool IsValid() const {
195 return valid_;
198 bool AttachShader(ShaderManager* manager, Shader* shader);
199 bool DetachShader(ShaderManager* manager, Shader* shader);
201 void CompileAttachedShaders();
202 bool AttachedShadersExist() const;
203 bool CanLink() const;
205 // Performs glLinkProgram and related activities.
206 bool Link(ShaderManager* manager,
207 VaryingsPackingOption varyings_packing_option,
208 const ShaderCacheCallback& shader_callback);
210 // Performs glValidateProgram and related activities.
211 void Validate();
213 const std::string* log_info() const {
214 return log_info_.get();
217 bool InUse() const {
218 DCHECK_GE(use_count_, 0);
219 return use_count_ != 0;
222 // Sets attribute-location binding from a glBindAttribLocation() call.
223 void SetAttribLocationBinding(const std::string& attrib, GLint location) {
224 bind_attrib_location_map_[attrib] = location;
227 // Sets uniform-location binding from a glBindUniformLocationCHROMIUM call.
228 // returns false if error.
229 bool SetUniformLocationBinding(const std::string& name, GLint location);
231 // Detects if the shader version combination is not valid.
232 bool DetectShaderVersionMismatch() const;
234 // Detects if there are attribute location conflicts from
235 // glBindAttribLocation() calls.
236 // We only consider the declared attributes in the program.
237 bool DetectAttribLocationBindingConflicts() const;
239 // Detects if there are uniform location conflicts from
240 // glBindUniformLocationCHROMIUM() calls.
241 // We only consider the statically used uniforms in the program.
242 bool DetectUniformLocationBindingConflicts() const;
244 // Detects if there are uniforms of the same name but different type
245 // or precision in vertex/fragment shaders.
246 // Return true and set the first found conflicting hashed name to
247 // conflicting_name if such cases are detected.
248 bool DetectUniformsMismatch(std::string* conflicting_name) const;
250 // Return true if a varying is statically used in fragment shader, but it
251 // is not declared in vertex shader.
252 bool DetectVaryingsMismatch(std::string* conflicting_name) const;
254 // Return true if any built-in invariant matching rules are broken as in
255 // GLSL ES spec 1.00.17, section 4.6.4, Invariance and Linkage.
256 bool DetectBuiltInInvariantConflicts() const;
258 // Return true if an uniform and an attribute share the same name.
259 bool DetectGlobalNameConflicts(std::string* conflicting_name) const;
261 // Return false if varyings can't be packed into the max available
262 // varying registers.
263 bool CheckVaryingsPacking(VaryingsPackingOption option) const;
265 void TransformFeedbackVaryings(GLsizei count, const char* const* varyings,
266 GLenum buffer_mode);
268 // Visible for testing
269 const LocationMap& bind_attrib_location_map() const {
270 return bind_attrib_location_map_;
273 const std::vector<std::string>& transform_feedback_varyings() const {
274 return transform_feedback_varyings_;
277 GLenum transform_feedback_buffer_mode() const {
278 return transform_feedback_buffer_mode_;
281 private:
282 friend class base::RefCounted<Program>;
283 friend class ProgramManager;
285 ~Program();
287 void set_log_info(const char* str) {
288 log_info_.reset(str ? new std::string(str) : NULL);
291 void ClearLinkStatus() {
292 link_status_ = false;
295 void IncUseCount() {
296 ++use_count_;
299 void DecUseCount() {
300 --use_count_;
301 DCHECK_GE(use_count_, 0);
304 void MarkAsDeleted() {
305 DCHECK(!deleted_);
306 deleted_ = true;
309 // Resets the program.
310 void Reset();
312 // Updates the program info after a successful link.
313 void Update();
315 // Process the program log, replacing the hashed names with original names.
316 std::string ProcessLogInfo(const std::string& log);
318 // Updates the program log info from GL
319 void UpdateLogInfo();
321 // Clears all the uniforms.
322 void ClearUniforms(std::vector<uint8>* zero_buffer);
324 // If long attribate names are mapped during shader translation, call
325 // glBindAttribLocation() again with the mapped names.
326 // This is called right before the glLink() call, but after shaders are
327 // translated.
328 void ExecuteBindAttribLocationCalls();
330 // The names of transform feedback varyings need to be hashed just
331 // like bound attributes' locations, just before the link call.
332 // Returns false upon failure.
333 bool ExecuteTransformFeedbackVaryingsCall();
335 void AddUniformInfo(
336 GLsizei size, GLenum type, GLint location, GLint fake_base_location,
337 const std::string& name, const std::string& original_name,
338 size_t* next_available_index);
340 // Query uniform data returned by ANGLE translator by the mapped name.
341 // Some drivers incorrectly return an uniform name of size-1 array without
342 // "[0]". In this case, we correct the name by appending "[0]" to it.
343 void GetCorrectedUniformData(
344 const std::string& name,
345 std::string* corrected_name, std::string* original_name,
346 GLsizei* size, GLenum* type) const;
348 // Query VertexAttrib data returned by ANGLE translator by the mapped name.
349 void GetVertexAttribData(
350 const std::string& name, std::string* original_name, GLenum* type) const;
352 void DetachShaders(ShaderManager* manager);
354 static inline GLint GetUniformInfoIndexFromFakeLocation(
355 GLint fake_location) {
356 return fake_location & 0xFFFF;
359 static inline GLint GetArrayElementIndexFromFakeLocation(
360 GLint fake_location) {
361 return (fake_location >> 16) & 0xFFFF;
364 ProgramManager* manager_;
366 int use_count_;
368 GLsizei max_attrib_name_length_;
370 // Attrib by index.
371 AttribInfoVector attrib_infos_;
373 // Attrib by location to index.
374 std::vector<GLint> attrib_location_to_index_map_;
376 GLsizei max_uniform_name_length_;
378 // Uniform info by index.
379 UniformInfoVector uniform_infos_;
381 // The indices of the uniforms that are samplers.
382 SamplerIndices sampler_indices_;
384 // The program this Program is tracking.
385 GLuint service_id_;
387 // Shaders by type of shader.
388 scoped_refptr<Shader>
389 attached_shaders_[kMaxAttachedShaders];
391 // True if this program is marked as deleted.
392 bool deleted_;
394 // This is true if glLinkProgram was successful at least once.
395 bool valid_;
397 // This is true if glLinkProgram was successful last time it was called.
398 bool link_status_;
400 // True if the uniforms have been cleared.
401 bool uniforms_cleared_;
403 // This is different than uniform_infos_.size() because
404 // that is a sparce array.
405 GLint num_uniforms_;
407 // Log info
408 scoped_ptr<std::string> log_info_;
410 // attribute-location binding map from glBindAttribLocation() calls.
411 LocationMap bind_attrib_location_map_;
413 // uniform-location binding map from glBindUniformLocationCHROMIUM() calls.
414 LocationMap bind_uniform_location_map_;
416 std::vector<std::string> transform_feedback_varyings_;
418 GLenum transform_feedback_buffer_mode_;
421 // Tracks the Programs.
423 // NOTE: To support shared resources an instance of this class will
424 // need to be shared by multiple GLES2Decoders.
425 class GPU_EXPORT ProgramManager {
426 public:
427 explicit ProgramManager(ProgramCache* program_cache,
428 uint32 max_varying_vectors);
429 ~ProgramManager();
431 // Must call before destruction.
432 void Destroy(bool have_context);
434 // Creates a new program.
435 Program* CreateProgram(GLuint client_id, GLuint service_id);
437 // Gets a program.
438 Program* GetProgram(GLuint client_id);
440 // Gets a client id for a given service id.
441 bool GetClientId(GLuint service_id, GLuint* client_id) const;
443 // Gets the shader cache
444 ProgramCache* program_cache() const;
446 // Marks a program as deleted. If it is not used the program will be deleted.
447 void MarkAsDeleted(ShaderManager* shader_manager, Program* program);
449 // Marks a program as used.
450 void UseProgram(Program* program);
452 // Makes a program as unused. If deleted the program will be removed.
453 void UnuseProgram(ShaderManager* shader_manager, Program* program);
455 // Clears the uniforms for this program.
456 void ClearUniforms(Program* program);
458 // Returns true if prefix is invalid for gl.
459 static bool IsInvalidPrefix(const char* name, size_t length);
461 // Check if a Program is owned by this ProgramManager.
462 bool IsOwned(Program* program) const;
464 static int32 MakeFakeLocation(int32 index, int32 element);
466 uint32 max_varying_vectors() const {
467 return max_varying_vectors_;
470 private:
471 friend class Program;
473 void StartTracking(Program* program);
474 void StopTracking(Program* program);
476 void RemoveProgramInfoIfUnused(
477 ShaderManager* shader_manager, Program* program);
479 // Info for each "successfully linked" program by service side program Id.
480 // TODO(gman): Choose a faster container.
481 typedef std::map<GLuint, scoped_refptr<Program> > ProgramMap;
482 ProgramMap programs_;
484 // Counts the number of Program allocated with 'this' as its manager.
485 // Allows to check no Program will outlive this.
486 unsigned int program_count_;
488 bool have_context_;
490 // Used to clear uniforms.
491 std::vector<uint8> zero_;
493 ProgramCache* program_cache_;
495 uint32 max_varying_vectors_;
497 DISALLOW_COPY_AND_ASSIGN(ProgramManager);
500 } // namespace gles2
501 } // namespace gpu
503 #endif // GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_