// Copyright (c) 2012 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_VERTEX_ATTRIB_MANAGER_H_ #define GPU_COMMAND_BUFFER_SERVICE_VERTEX_ATTRIB_MANAGER_H_ #include #include #include #include #include "base/logging.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" namespace gpu { namespace gles2 { class FeatureInfo; class GLES2Decoder; class Program; class VertexArrayManager; // Info about a Vertex Attribute. This is used to track what the user currently // has bound on each Vertex Attribute so that checking can be done at // glDrawXXX time. class GPU_EXPORT VertexAttrib { public: typedef std::list VertexAttribList; VertexAttrib(); ~VertexAttrib(); // Returns true if this VertexAttrib can access index. bool CanAccess(GLuint index) const; Buffer* buffer() const { return buffer_.get(); } GLsizei offset() const { return offset_; } GLuint index() const { return index_; } GLint size() const { return size_; } GLenum type() const { return type_; } GLboolean normalized() const { return normalized_; } GLsizei gl_stride() const { return gl_stride_; } GLuint divisor() const { return divisor_; } GLboolean integer() const { return integer_; } bool enabled() const { return enabled_; } // Find the maximum vertex accessed, accounting for instancing. GLuint MaxVertexAccessed(GLsizei primcount, GLuint max_vertex_accessed) const { return divisor_ ? ((primcount - 1) / divisor_) : max_vertex_accessed; } bool is_client_side_array() const { return is_client_side_array_; } void set_is_client_side_array(bool value) { is_client_side_array_ = value; } private: friend class VertexAttribManager; void set_enabled(bool enabled) { enabled_ = enabled; } void set_index(GLuint index) { index_ = index; } void SetList(VertexAttribList* new_list) { DCHECK(new_list); if (list_) { list_->erase(it_); } it_ = new_list->insert(new_list->end(), this); list_ = new_list; } void SetInfo( Buffer* buffer, GLint size, GLenum type, GLboolean normalized, GLsizei gl_stride, GLsizei real_stride, GLsizei offset, GLboolean integer); void SetDivisor(GLsizei divisor) { divisor_ = divisor; } void Unbind(Buffer* buffer); // The index of this attrib. GLuint index_; // Whether or not this attribute is enabled. bool enabled_; // number of components (1, 2, 3, 4) GLint size_; // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer. GLenum type_; // The offset into the buffer. GLsizei offset_; GLboolean normalized_; // The stride passed to glVertexAttribPointer. GLsizei gl_stride_; // The stride that will be used to access the buffer. This is the actual // stide, NOT the GL bogus stride. In other words there is never a stride // of 0. GLsizei real_stride_; GLsizei divisor_; GLboolean integer_; // Will be true if this was assigned to a client side array. bool is_client_side_array_; // The buffer bound to this attribute. scoped_refptr buffer_; // List this info is on. VertexAttribList* list_; // Iterator for list this info is on. Enabled/Disabled VertexAttribList::iterator it_; }; // Manages vertex attributes. // This class also acts as the service-side representation of a // vertex array object and it's contained state. class GPU_EXPORT VertexAttribManager : public base::RefCounted { public: typedef std::list VertexAttribList; VertexAttribManager(); void Initialize(uint32_t num_vertex_attribs, bool init_attribs); bool Enable(GLuint index, bool enable); bool HaveFixedAttribs() const { return num_fixed_attribs_ != 0; } const VertexAttribList& GetEnabledVertexAttribs() const { return enabled_vertex_attribs_; } VertexAttrib* GetVertexAttrib(GLuint index) { if (index < vertex_attribs_.size()) { return &vertex_attribs_[index]; } return NULL; } void SetAttribInfo( GLuint index, Buffer* buffer, GLint size, GLenum type, GLboolean normalized, GLsizei gl_stride, GLsizei real_stride, GLsizei offset, GLboolean integer) { VertexAttrib* attrib = GetVertexAttrib(index); if (attrib) { if (attrib->type() == GL_FIXED) { --num_fixed_attribs_; } if (type == GL_FIXED) { ++num_fixed_attribs_; } attrib->SetInfo(buffer, size, type, normalized, gl_stride, real_stride, offset, integer); } } void SetDivisor(GLuint index, GLuint divisor) { VertexAttrib* attrib = GetVertexAttrib(index); if (attrib) { attrib->SetDivisor(divisor); } } void SetElementArrayBuffer(Buffer* buffer); Buffer* element_array_buffer() const { return element_array_buffer_.get(); } GLuint service_id() const { return service_id_; } void Unbind(Buffer* buffer); bool IsDeleted() const { return deleted_; } bool IsValid() const { return !IsDeleted(); } size_t num_attribs() const { return vertex_attribs_.size(); } bool ValidateBindings( const char* function_name, GLES2Decoder* decoder, FeatureInfo* feature_info, Program* current_program, GLuint max_vertex_accessed, bool instanced, GLsizei primcount); private: friend class VertexArrayManager; friend class VertexArrayManagerTest; friend class base::RefCounted; // Used when creating from a VertexArrayManager VertexAttribManager(VertexArrayManager* manager, GLuint service_id, uint32_t num_vertex_attribs); ~VertexAttribManager(); void MarkAsDeleted() { deleted_ = true; } // number of attribs using type GL_FIXED. int num_fixed_attribs_; // Info for each vertex attribute saved so we can check at glDrawXXX time // if it is safe to draw. std::vector vertex_attribs_; // The currently bound element array buffer. If this is 0 it is illegal // to call glDrawElements. scoped_refptr element_array_buffer_; // Lists for which vertex attribs are enabled, disabled. VertexAttribList enabled_vertex_attribs_; VertexAttribList disabled_vertex_attribs_; // The VertexArrayManager that owns this VertexAttribManager VertexArrayManager* manager_; // True if deleted. bool deleted_; // Service side vertex array object id. GLuint service_id_; }; } // namespace gles2 } // namespace gpu #endif // GPU_COMMAND_BUFFER_SERVICE_VERTEX_ATTRIB_MANAGER_H_