blob: dca232bf242bcd08a0c9e582d66dc5b636da37c6 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000016#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000017#include "gpu/command_buffer/service/shader_manager.h"
18#include "gpu/gpu_export.h"
19
20namespace gpu {
21namespace gles2 {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000022
Torne (Richard Coles)58218062012-11-14 11:43:16 +000023class FeatureInfo;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000024class 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};
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000316
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:
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000323 explicit ProgramManager(ProgramCache* program_cache);
324 ~ProgramManager();
325
326 // Must call before destruction.
327 void Destroy(bool have_context);
328
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000329 // Creates a new program.
330 Program* CreateProgram(GLuint client_id, GLuint service_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000331
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000332 // Gets a program.
333 Program* GetProgram(GLuint client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000334
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
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000341 // Marks a program as deleted. If it is not used the program will be deleted.
342 void MarkAsDeleted(ShaderManager* shader_manager, Program* program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000343
344 // Marks a program as used.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000345 void UseProgram(Program* program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000346
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000347 // Makes a program as unused. If deleted the program will be removed.
348 void UnuseProgram(ShaderManager* shader_manager, Program* program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000349
350 // Clears the uniforms for this program.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000351 void ClearUniforms(Program* program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000352
353 // Returns true if prefix is invalid for gl.
354 static bool IsInvalidPrefix(const char* name, size_t length);
355
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000356 // Check if a Program is owned by this ProgramManager.
357 bool IsOwned(Program* program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000358
359 static int32 MakeFakeLocation(int32 index, int32 element);
360
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000361 void DoCompileShader(Shader* shader,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000362 ShaderTranslator* translator,
363 FeatureInfo* feature_info);
364
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000365 private:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000366 friend class Program;
367
368 void StartTracking(Program* program);
369 void StopTracking(Program* program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000370
371 // Info for each "successfully linked" program by service side program Id.
372 // TODO(gman): Choose a faster container.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000373 typedef std::map<GLuint, scoped_refptr<Program> > ProgramMap;
374 ProgramMap programs_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000375
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000376 // 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_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000379
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(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000390 ShaderManager* shader_manager, Program* program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000391
392 DISALLOW_COPY_AND_ASSIGN(ProgramManager);
393};
394
395} // namespace gles2
396} // namespace gpu
397
398#endif // GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_