Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / gpu / command_buffer / service / program_manager.h
blobbcc3630f104bd9d9e93d8b62c34cbc24b0853745
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;
27 class ShaderTranslator;
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;
36 enum VaryingsPackingOption {
37 kCountOnlyStaticallyUsed,
38 kCountAll
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,
55 struct UniformInfo {
56 UniformInfo();
57 UniformInfo(
58 GLsizei _size, GLenum _type, GLint _fake_location_base,
59 const std::string& _name);
60 ~UniformInfo();
62 bool IsValid() const {
63 return size != 0;
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;
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;
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) {
88 GLsizei size;
89 GLenum type;
90 GLint location;
91 std::string name;
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;
99 Program(ProgramManager* manager, GLuint service_id);
101 GLuint service_id() const {
102 return service_id_;
105 const SamplerIndices& sampler_indices() {
106 return sampler_indices_;
109 const AttribInfoVector& GetAttribInfos() const {
110 return attrib_infos_;
113 const VertexAttrib* GetAttribInfo(GLint index) const {
114 return (static_cast<size_t>(index) < attrib_infos_.size()) ?
115 &attrib_infos_[index] : NULL;
118 GLint GetAttribLocation(const std::string& name) const;
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];
127 return NULL;
130 const UniformInfo* GetUniformInfo(GLint index) const;
132 // If the original name is not found, return NULL.
133 const std::string* GetAttribMappedName(
134 const std::string& original_name) const;
136 // If the hashed name is not found, return NULL.
137 const std::string* GetOriginalNameFromHashedName(
138 const std::string& hashed_name) const;
140 // Gets the fake location of a uniform by name.
141 GLint GetUniformFakeLocation(const std::string& name) const;
143 // Gets the UniformInfo of a uniform by location.
144 const UniformInfo* GetUniformInfoByFakeLocation(
145 GLint fake_location, GLint* real_location, GLint* array_index) const;
147 // Gets all the program info.
148 void GetProgramInfo(
149 ProgramManager* manager, CommonDecoder::Bucket* bucket) const;
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);
160 bool IsDeleted() const {
161 return deleted_;
164 void GetProgramiv(GLenum pname, GLint* params);
166 bool IsValid() const {
167 return valid_;
170 bool AttachShader(ShaderManager* manager, Shader* shader);
171 bool DetachShader(ShaderManager* manager, Shader* shader);
173 bool CanLink() const;
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);
182 // Performs glValidateProgram and related activities.
183 void Validate();
185 const std::string* log_info() const {
186 return log_info_.get();
189 bool InUse() const {
190 DCHECK_GE(use_count_, 0);
191 return use_count_ != 0;
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;
199 // Sets uniform-location binding from a glBindUniformLocationCHROMIUM call.
200 // returns false if error.
201 bool SetUniformLocationBinding(const std::string& name, GLint location);
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;
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;
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;
218 // Return true if an uniform and an attribute share the same name.
219 bool DetectGlobalNameConflicts(std::string* conflicting_name) const;
221 // Return false if varyings can't be packed into the max available
222 // varying registers.
223 bool CheckVaryingsPacking(VaryingsPackingOption option) const;
225 // Visible for testing
226 const LocationMap& bind_attrib_location_map() const {
227 return bind_attrib_location_map_;
230 private:
231 friend class base::RefCounted<Program>;
232 friend class ProgramManager;
234 ~Program();
236 void set_log_info(const char* str) {
237 log_info_.reset(str ? new std::string(str) : NULL);
240 void ClearLinkStatus() {
241 link_status_ = false;
244 void IncUseCount() {
245 ++use_count_;
248 void DecUseCount() {
249 --use_count_;
250 DCHECK_GE(use_count_, 0);
253 void MarkAsDeleted() {
254 DCHECK(!deleted_);
255 deleted_ = true;
258 // Resets the program.
259 void Reset();
261 // Updates the program info after a successful link.
262 void Update();
264 // Process the program log, replacing the hashed names with original names.
265 std::string ProcessLogInfo(const std::string& log);
267 // Updates the program log info from GL
268 void UpdateLogInfo();
270 // Clears all the uniforms.
271 void ClearUniforms(std::vector<uint8>* zero_buffer);
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();
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);
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;
288 void DetachShaders(ShaderManager* manager);
290 static inline GLint GetUniformInfoIndexFromFakeLocation(
291 GLint fake_location) {
292 return fake_location & 0xFFFF;
295 static inline GLint GetArrayElementIndexFromFakeLocation(
296 GLint fake_location) {
297 return (fake_location >> 16) & 0xFFFF;
300 ProgramManager* manager_;
302 int use_count_;
304 GLsizei max_attrib_name_length_;
306 // Attrib by index.
307 AttribInfoVector attrib_infos_;
309 // Attrib by location to index.
310 std::vector<GLint> attrib_location_to_index_map_;
312 GLsizei max_uniform_name_length_;
314 // Uniform info by index.
315 UniformInfoVector uniform_infos_;
317 // The indices of the uniforms that are samplers.
318 SamplerIndices sampler_indices_;
320 // The program this Program is tracking.
321 GLuint service_id_;
323 // Shaders by type of shader.
324 scoped_refptr<Shader>
325 attached_shaders_[kMaxAttachedShaders];
327 // True if this program is marked as deleted.
328 bool deleted_;
330 // This is true if glLinkProgram was successful at least once.
331 bool valid_;
333 // This is true if glLinkProgram was successful last time it was called.
334 bool link_status_;
336 // True if the uniforms have been cleared.
337 bool uniforms_cleared_;
339 // This is different than uniform_infos_.size() because
340 // that is a sparce array.
341 GLint num_uniforms_;
343 // Log info
344 scoped_ptr<std::string> log_info_;
346 // attribute-location binding map from glBindAttribLocation() calls.
347 LocationMap bind_attrib_location_map_;
349 // uniform-location binding map from glBindUniformLocationCHROMIUM() calls.
350 LocationMap bind_uniform_location_map_;
353 // Tracks the Programs.
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();
363 // Must call before destruction.
364 void Destroy(bool have_context);
366 // Creates a new program.
367 Program* CreateProgram(GLuint client_id, GLuint service_id);
369 // Gets a program.
370 Program* GetProgram(GLuint client_id);
372 // Gets a client id for a given service id.
373 bool GetClientId(GLuint service_id, GLuint* client_id) const;
375 // Gets the shader cache
376 ProgramCache* program_cache() const;
378 // Marks a program as deleted. If it is not used the program will be deleted.
379 void MarkAsDeleted(ShaderManager* shader_manager, Program* program);
381 // Marks a program as used.
382 void UseProgram(Program* program);
384 // Makes a program as unused. If deleted the program will be removed.
385 void UnuseProgram(ShaderManager* shader_manager, Program* program);
387 // Clears the uniforms for this program.
388 void ClearUniforms(Program* program);
390 // Returns true if prefix is invalid for gl.
391 static bool IsInvalidPrefix(const char* name, size_t length);
393 // Check if a Program is owned by this ProgramManager.
394 bool IsOwned(Program* program);
396 static int32 MakeFakeLocation(int32 index, int32 element);
398 uint32 max_varying_vectors() const {
399 return max_varying_vectors_;
402 private:
403 friend class Program;
405 void StartTracking(Program* program);
406 void StopTracking(Program* program);
408 void RemoveProgramInfoIfUnused(
409 ShaderManager* shader_manager, Program* program);
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_;
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_;
420 bool have_context_;
422 // Used to clear uniforms.
423 std::vector<uint8> zero_;
425 ProgramCache* program_cache_;
427 uint32 max_varying_vectors_;
429 DISALLOW_COPY_AND_ASSIGN(ProgramManager);
432 } // namespace gles2
433 } // namespace gpu
435 #endif // GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_