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_
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"
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
> {
33 static const int kMaxAttachedShaders
= 2;
35 enum VaryingsPackingOption
{
36 kCountOnlyStaticallyUsed
,
50 kUniformMatrix2f
= 1 << 8,
51 kUniformMatrix3f
= 1 << 9,
52 kUniformMatrix4f
= 1 << 10,
58 GLsizei _size
, GLenum _type
, GLint _fake_location_base
,
59 const std::string
& _name
);
62 bool IsValid() const {
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
;
73 uint32 accepts_api_type
;
74 GLint fake_location_base
;
77 std::vector
<GLint
> element_locations
;
78 std::vector
<GLuint
> texture_units
;
81 VertexAttrib(GLsizei _size
, GLenum _type
, const 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 {
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
& original_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
];
124 return &attrib_infos_
[index
];
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.
149 ProgramManager
* manager
, CommonDecoder::Bucket
* bucket
) const;
151 // Gets all the UniformBlock info.
152 // Return false on overflow.
153 bool GetUniformBlocks(CommonDecoder::Bucket
* bucket
) const;
155 // Gets all the TransformFeedbackVarying info.
156 // Return false on overflow.
157 bool GetTransformFeedbackVaryings(CommonDecoder::Bucket
* bucket
) const;
159 // Gather all info through glGetActiveUniformsiv, except for size, type,
160 // name_length, which we gather through glGetActiveUniform in
161 // glGetProgramInfoCHROMIUM.
162 bool GetUniformsES3(CommonDecoder::Bucket
* bucket
) const;
164 // Sets the sampler values for a uniform.
165 // This is safe to call for any location. If the location is not
166 // a sampler uniform nothing will happen.
167 // Returns false if fake_location is a sampler and any value
168 // is >= num_texture_units. Returns true otherwise.
170 GLint num_texture_units
, GLint fake_location
,
171 GLsizei count
, const GLint
* value
);
173 bool IsDeleted() const {
177 void GetProgramiv(GLenum pname
, GLint
* params
);
179 bool IsValid() const {
183 bool AttachShader(ShaderManager
* manager
, Shader
* shader
);
184 bool DetachShader(ShaderManager
* manager
, Shader
* shader
);
186 void CompileAttachedShaders();
187 bool AttachedShadersExist() const;
188 bool CanLink() const;
190 // Performs glLinkProgram and related activities.
191 bool Link(ShaderManager
* manager
,
192 VaryingsPackingOption varyings_packing_option
,
193 const ShaderCacheCallback
& shader_callback
);
195 // Performs glValidateProgram and related activities.
198 const std::string
* log_info() const {
199 return log_info_
.get();
203 DCHECK_GE(use_count_
, 0);
204 return use_count_
!= 0;
207 // Sets attribute-location binding from a glBindAttribLocation() call.
208 void SetAttribLocationBinding(const std::string
& attrib
, GLint location
) {
209 bind_attrib_location_map_
[attrib
] = location
;
212 // Sets uniform-location binding from a glBindUniformLocationCHROMIUM call.
213 // returns false if error.
214 bool SetUniformLocationBinding(const std::string
& name
, GLint location
);
216 // Detects if there are attribute location conflicts from
217 // glBindAttribLocation() calls.
218 // We only consider the declared attributes in the program.
219 bool DetectAttribLocationBindingConflicts() const;
221 // Detects if there are uniforms of the same name but different type
222 // or precision in vertex/fragment shaders.
223 // Return true and set the first found conflicting hashed name to
224 // conflicting_name if such cases are detected.
225 bool DetectUniformsMismatch(std::string
* conflicting_name
) const;
227 // Return true if a varying is statically used in fragment shader, but it
228 // is not declared in vertex shader.
229 bool DetectVaryingsMismatch(std::string
* conflicting_name
) const;
231 // Return true if any built-in invariant matching rules are broken as in
232 // GLSL ES spec 1.00.17, section 4.6.4, Invariance and Linkage.
233 bool DetectBuiltInInvariantConflicts() const;
235 // Return true if an uniform and an attribute share the same name.
236 bool DetectGlobalNameConflicts(std::string
* conflicting_name
) const;
238 // Return false if varyings can't be packed into the max available
239 // varying registers.
240 bool CheckVaryingsPacking(VaryingsPackingOption option
) const;
242 // Visible for testing
243 const LocationMap
& bind_attrib_location_map() const {
244 return bind_attrib_location_map_
;
248 friend class base::RefCounted
<Program
>;
249 friend class ProgramManager
;
253 void set_log_info(const char* str
) {
254 log_info_
.reset(str
? new std::string(str
) : NULL
);
257 void ClearLinkStatus() {
258 link_status_
= false;
267 DCHECK_GE(use_count_
, 0);
270 void MarkAsDeleted() {
275 // Resets the program.
278 // Updates the program info after a successful link.
281 // Process the program log, replacing the hashed names with original names.
282 std::string
ProcessLogInfo(const std::string
& log
);
284 // Updates the program log info from GL
285 void UpdateLogInfo();
287 // Clears all the uniforms.
288 void ClearUniforms(std::vector
<uint8
>* zero_buffer
);
290 // If long attribate names are mapped during shader translation, call
291 // glBindAttribLocation() again with the mapped names.
292 // This is called right before the glLink() call, but after shaders are
294 void ExecuteBindAttribLocationCalls();
297 GLsizei size
, GLenum type
, GLint location
, GLint fake_base_location
,
298 const std::string
& name
, const std::string
& original_name
,
299 size_t* next_available_index
);
301 // Query uniform data returned by ANGLE translator by the mapped name.
302 // Some drivers incorrectly return an uniform name of size-1 array without
303 // "[0]". In this case, we correct the name by appending "[0]" to it.
304 void GetCorrectedUniformData(
305 const std::string
& name
,
306 std::string
* corrected_name
, std::string
* original_name
,
307 GLsizei
* size
, GLenum
* type
) const;
309 // Query VertexAttrib data returned by ANGLE translator by the mapped name.
310 void GetVertexAttribData(
311 const std::string
& name
, std::string
* original_name
, GLenum
* type
) const;
313 void DetachShaders(ShaderManager
* manager
);
315 static inline GLint
GetUniformInfoIndexFromFakeLocation(
316 GLint fake_location
) {
317 return fake_location
& 0xFFFF;
320 static inline GLint
GetArrayElementIndexFromFakeLocation(
321 GLint fake_location
) {
322 return (fake_location
>> 16) & 0xFFFF;
325 ProgramManager
* manager_
;
329 GLsizei max_attrib_name_length_
;
332 AttribInfoVector attrib_infos_
;
334 // Attrib by location to index.
335 std::vector
<GLint
> attrib_location_to_index_map_
;
337 GLsizei max_uniform_name_length_
;
339 // Uniform info by index.
340 UniformInfoVector uniform_infos_
;
342 // The indices of the uniforms that are samplers.
343 SamplerIndices sampler_indices_
;
345 // The program this Program is tracking.
348 // Shaders by type of shader.
349 scoped_refptr
<Shader
>
350 attached_shaders_
[kMaxAttachedShaders
];
352 // True if this program is marked as deleted.
355 // This is true if glLinkProgram was successful at least once.
358 // This is true if glLinkProgram was successful last time it was called.
361 // True if the uniforms have been cleared.
362 bool uniforms_cleared_
;
364 // This is different than uniform_infos_.size() because
365 // that is a sparce array.
369 scoped_ptr
<std::string
> log_info_
;
371 // attribute-location binding map from glBindAttribLocation() calls.
372 LocationMap bind_attrib_location_map_
;
374 // uniform-location binding map from glBindUniformLocationCHROMIUM() calls.
375 LocationMap bind_uniform_location_map_
;
378 // Tracks the Programs.
380 // NOTE: To support shared resources an instance of this class will
381 // need to be shared by multiple GLES2Decoders.
382 class GPU_EXPORT ProgramManager
{
384 explicit ProgramManager(ProgramCache
* program_cache
,
385 uint32 max_varying_vectors
);
388 // Must call before destruction.
389 void Destroy(bool have_context
);
391 // Creates a new program.
392 Program
* CreateProgram(GLuint client_id
, GLuint service_id
);
395 Program
* GetProgram(GLuint client_id
);
397 // Gets a client id for a given service id.
398 bool GetClientId(GLuint service_id
, GLuint
* client_id
) const;
400 // Gets the shader cache
401 ProgramCache
* program_cache() const;
403 // Marks a program as deleted. If it is not used the program will be deleted.
404 void MarkAsDeleted(ShaderManager
* shader_manager
, Program
* program
);
406 // Marks a program as used.
407 void UseProgram(Program
* program
);
409 // Makes a program as unused. If deleted the program will be removed.
410 void UnuseProgram(ShaderManager
* shader_manager
, Program
* program
);
412 // Clears the uniforms for this program.
413 void ClearUniforms(Program
* program
);
415 // Returns true if prefix is invalid for gl.
416 static bool IsInvalidPrefix(const char* name
, size_t length
);
418 // Check if a Program is owned by this ProgramManager.
419 bool IsOwned(Program
* program
);
421 static int32
MakeFakeLocation(int32 index
, int32 element
);
423 uint32
max_varying_vectors() const {
424 return max_varying_vectors_
;
428 friend class Program
;
430 void StartTracking(Program
* program
);
431 void StopTracking(Program
* program
);
433 void RemoveProgramInfoIfUnused(
434 ShaderManager
* shader_manager
, Program
* program
);
436 // Info for each "successfully linked" program by service side program Id.
437 // TODO(gman): Choose a faster container.
438 typedef std::map
<GLuint
, scoped_refptr
<Program
> > ProgramMap
;
439 ProgramMap programs_
;
441 // Counts the number of Program allocated with 'this' as its manager.
442 // Allows to check no Program will outlive this.
443 unsigned int program_count_
;
447 // Used to clear uniforms.
448 std::vector
<uint8
> zero_
;
450 ProgramCache
* program_cache_
;
452 uint32 max_varying_vectors_
;
454 DISALLOW_COPY_AND_ASSIGN(ProgramManager
);
460 #endif // GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_