// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_ #define GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_ #include #include #include #include "base/basictypes.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/shader_manager.h" namespace gpu { namespace gles2 { // Tracks the Programs. // // NOTE: To support shared resources an instance of this class will // need to be shared by multiple GLES2Decoders. class ProgramManager { public: // This is used to track which attributes a particular program needs // so we can verify at glDrawXXX time that every attribute is either disabled // or if enabled that it points to a valid source. class ProgramInfo : public base::RefCounted { public: typedef scoped_refptr Ref; static const int kMaxAttachedShaders = 2; struct UniformInfo { UniformInfo(GLsizei _size, GLenum _type, const std::string& _name); ~UniformInfo(); bool IsSampler() const { return type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE; } GLsizei size; GLenum type; bool is_array; std::string name; std::vector element_locations; std::vector texture_units; }; struct VertexAttribInfo { VertexAttribInfo(GLsizei _size, GLenum _type, const std::string& _name, GLint _location) : size(_size), type(_type), location(_location), name(_name) { } GLsizei size; GLenum type; GLint location; std::string name; }; typedef std::vector UniformInfoVector; typedef std::vector AttribInfoVector; typedef std::vector SamplerIndices; explicit ProgramInfo(GLuint service_id); GLuint service_id() const { return service_id_; } const SamplerIndices& sampler_indices() { return sampler_indices_; } const AttribInfoVector& GetAttribInfos() const { return attrib_infos_; } const VertexAttribInfo* GetAttribInfo(GLint index) const { return (static_cast(index) < attrib_infos_.size()) ? &attrib_infos_[index] : NULL; } GLint GetAttribLocation(const std::string& name) const; const VertexAttribInfo* GetAttribInfoByLocation(GLuint location) const { if (location < attrib_location_to_index_map_.size()) { GLint index = attrib_location_to_index_map_[location]; if (index >= 0) { return &attrib_infos_[index]; } } return NULL; } const UniformInfo* GetUniformInfo(GLint index) const { return (static_cast(index) < uniform_infos_.size()) ? &uniform_infos_[index] : NULL; } // Gets the location of a uniform by name. GLint GetUniformLocation(const std::string& name) const; // Gets the UniformInfo of a uniform by location. const UniformInfo* GetUniformInfoByLocation( GLint location, GLint* array_index) const; // Sets the sampler values for a uniform. // This is safe to call for any location. If the location is not // a sampler uniform nothing will happen. bool SetSamplers(GLint location, GLsizei count, const GLint* value); bool IsDeleted() const { return service_id_ == 0; } void GetProgramiv(GLenum pname, GLint* params); bool IsValid() const { return valid_; } bool AttachShader(ShaderManager* manager, ShaderManager::ShaderInfo* info); bool DetachShader(ShaderManager* manager, ShaderManager::ShaderInfo* info); bool CanLink() const; // Performs glLinkProgram and related activities. void Link(); // Performs glValidateProgram and related activities. void Validate(); const std::string* log_info() const { return log_info_.get(); } bool InUse() const { DCHECK_GE(use_count_, 0); return use_count_ != 0; } private: friend class base::RefCounted; friend class ProgramManager; // Info for each location struct LocationInfo { LocationInfo() : uniform_index(-1), array_index(-1) { } LocationInfo(GLint _uniform_index, GLint _array_index) : uniform_index(_uniform_index), array_index(_array_index) { } GLint uniform_index; // index of UniformInfo in uniform_infos_. GLint array_index; // index of location when used in array. }; ~ProgramInfo(); void set_log_info(const char* str) { log_info_.reset(str ? new std::string(str) : NULL); } void ClearLinkStatus() { link_status_ = false; } void IncUseCount() { ++use_count_; } void DecUseCount() { --use_count_; DCHECK_GE(use_count_, 0); } void MarkAsDeleted() { DCHECK_NE(service_id_, 0u); service_id_ = 0; } // Resets the program. void Reset(); // Updates the program info after a successful link. void Update(); // Updates the program log info from GL void UpdateLogInfo(); const UniformInfo* AddUniformInfo( GLsizei size, GLenum type, GLint location, const std::string& name, const std::string& original_name); void GetCorrectedVariableInfo( bool use_uniforms, const std::string& name, std::string* corrected_name, std::string* original_name, GLsizei* size, GLenum* type) const; void DetachShaders(ShaderManager* manager); int use_count_; GLsizei max_attrib_name_length_; // Attrib by index. AttribInfoVector attrib_infos_; // Attrib by location to index. std::vector attrib_location_to_index_map_; GLsizei max_uniform_name_length_; // Uniform info by index. UniformInfoVector uniform_infos_; // Info for each location. std::vector location_infos_; // The indices of the uniforms that are samplers. SamplerIndices sampler_indices_; // The program this ProgramInfo is tracking. GLuint service_id_; // Shaders by type of shader. ShaderManager::ShaderInfo::Ref attached_shaders_[kMaxAttachedShaders]; // This is true if glLinkProgram was successful at least once. bool valid_; // This is true if glLinkProgram was successful last time it was called. bool link_status_; // Log info scoped_ptr log_info_; }; ProgramManager(); ~ProgramManager(); // Must call before destruction. void Destroy(bool have_context); // Creates a new program info. ProgramInfo* CreateProgramInfo(GLuint client_id, GLuint service_id); // Gets a program info ProgramInfo* GetProgramInfo(GLuint client_id); // Gets a client id for a given service id. bool GetClientId(GLuint service_id, GLuint* client_id) const; // Marks a program as deleted. If it is not used the info will be deleted. void MarkAsDeleted(ShaderManager* shader_manager, ProgramInfo* info); // Marks a program as used. void UseProgram(ProgramInfo* info); // Makes a program as unused. If deleted the program info will be removed. void UnuseProgram(ShaderManager* shader_manager, ProgramInfo* info); // Returns true if prefix is invalid for gl. static bool IsInvalidPrefix(const char* name, size_t length); // Check if a ProgramInfo is owned by this ProgramManager. bool IsOwned(ProgramInfo* info); private: // Info for each "successfully linked" program by service side program Id. // TODO(gman): Choose a faster container. typedef std::map ProgramInfoMap; ProgramInfoMap program_infos_; void RemoveProgramInfoIfUnused( ShaderManager* shader_manager, ProgramInfo* info); DISALLOW_COPY_AND_ASSIGN(ProgramManager); }; } // namespace gles2 } // namespace gpu #endif // GPU_COMMAND_BUFFER_SERVICE_PROGRAM_MANAGER_H_