| // 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_BUFFER_MANAGER_H_ | 
 | #define GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_ | 
 |  | 
 | #include <map> | 
 | #include "base/basictypes.h" | 
 | #include "base/containers/hash_tables.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/memory_tracking.h" | 
 | #include "gpu/gpu_export.h" | 
 |  | 
 | namespace gpu { | 
 | namespace gles2 { | 
 |  | 
 | class BufferManager; | 
 | struct ContextState; | 
 | class ErrorState; | 
 | class FeatureInfo; | 
 | class TestHelper; | 
 |  | 
 | // Info about Buffers currently in the system. | 
 | class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { | 
 |  public: | 
 |   Buffer(BufferManager* manager, GLuint service_id); | 
 |  | 
 |   GLuint service_id() const { | 
 |     return service_id_; | 
 |   } | 
 |  | 
 |   GLenum target() const { | 
 |     return target_; | 
 |   } | 
 |  | 
 |   GLsizeiptr size() const { | 
 |     return size_; | 
 |   } | 
 |  | 
 |   GLenum usage() const { | 
 |     return usage_; | 
 |   } | 
 |  | 
 |   // Gets the maximum value in the buffer for the given range interpreted as | 
 |   // the given type. Returns false if offset and count are out of range. | 
 |   // offset is in bytes. | 
 |   // count is in elements of type. | 
 |   bool GetMaxValueForRange(GLuint offset, GLsizei count, GLenum type, | 
 |                            GLuint* max_value); | 
 |  | 
 |   // Returns a pointer to shadowed data. | 
 |   const void* GetRange(GLintptr offset, GLsizeiptr size) const; | 
 |  | 
 |   bool IsDeleted() const { | 
 |     return deleted_; | 
 |   } | 
 |  | 
 |   bool IsValid() const { | 
 |     return target() && !IsDeleted(); | 
 |   } | 
 |  | 
 |   bool IsClientSideArray() const { | 
 |     return is_client_side_array_; | 
 |   } | 
 |  | 
 |  private: | 
 |   friend class BufferManager; | 
 |   friend class BufferManagerTestBase; | 
 |   friend class base::RefCounted<Buffer>; | 
 |  | 
 |   // Represents a range in a buffer. | 
 |   class Range { | 
 |    public: | 
 |     Range(GLuint offset, GLsizei count, GLenum type) | 
 |         : offset_(offset), | 
 |           count_(count), | 
 |           type_(type) { | 
 |     } | 
 |  | 
 |     // A less functor provided for std::map so it can find ranges. | 
 |     struct Less { | 
 |       bool operator() (const Range& lhs, const Range& rhs) const { | 
 |         if (lhs.offset_ != rhs.offset_) { | 
 |           return lhs.offset_ < rhs.offset_; | 
 |         } | 
 |         if (lhs.count_ != rhs.count_) { | 
 |           return lhs.count_ < rhs.count_; | 
 |         } | 
 |         return lhs.type_ < rhs.type_; | 
 |       } | 
 |     }; | 
 |  | 
 |    private: | 
 |     GLuint offset_; | 
 |     GLsizei count_; | 
 |     GLenum type_; | 
 |   }; | 
 |  | 
 |   ~Buffer(); | 
 |  | 
 |   void set_target(GLenum target) { | 
 |     DCHECK_EQ(target_, 0u);  // you can only set this once. | 
 |     target_ = target; | 
 |   } | 
 |  | 
 |   bool shadowed() const { | 
 |     return shadowed_; | 
 |   } | 
 |  | 
 |   void MarkAsDeleted() { | 
 |     deleted_ = true; | 
 |   } | 
 |  | 
 |   // Sets the size, usage and initial data of a buffer. | 
 |   // If shadow is true then if data is NULL buffer will be initialized to 0. | 
 |   void SetInfo( | 
 |       GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data, | 
 |       bool is_client_side_array); | 
 |  | 
 |   // Sets a range of data for this buffer. Returns false if the offset or size | 
 |   // is out of range. | 
 |   bool SetRange( | 
 |     GLintptr offset, GLsizeiptr size, const GLvoid * data); | 
 |  | 
 |   // Clears any cache of index ranges. | 
 |   void ClearCache(); | 
 |  | 
 |   // Check if an offset, size range is valid for the current buffer. | 
 |   bool CheckRange(GLintptr offset, GLsizeiptr size) const; | 
 |  | 
 |   // The manager that owns this Buffer. | 
 |   BufferManager* manager_; | 
 |  | 
 |   // A copy of the data in the buffer. This data is only kept if the target | 
 |   // is backed_ = true. | 
 |   scoped_ptr<int8[]> shadow_; | 
 |  | 
 |   // Size of buffer. | 
 |   GLsizeiptr size_; | 
 |  | 
 |   // True if deleted. | 
 |   bool deleted_; | 
 |  | 
 |   // Whether or not the data is shadowed. | 
 |   bool shadowed_; | 
 |  | 
 |   // Whether or not this Buffer is not uploaded to the GPU but just | 
 |   // sitting in local memory. | 
 |   bool is_client_side_array_; | 
 |  | 
 |   // Service side buffer id. | 
 |   GLuint service_id_; | 
 |  | 
 |   // The type of buffer. 0 = unset, GL_BUFFER_ARRAY = vertex data, | 
 |   // GL_ELEMENT_BUFFER_ARRAY = index data. | 
 |   // Once set a buffer can not be used for something else. | 
 |   GLenum target_; | 
 |  | 
 |   // Usage of buffer. | 
 |   GLenum usage_; | 
 |  | 
 |   // A map of ranges to the highest value in that range of a certain type. | 
 |   typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap; | 
 |   RangeToMaxValueMap range_set_; | 
 | }; | 
 |  | 
 | // This class keeps track of the buffers and their sizes so we can do | 
 | // bounds checking. | 
 | // | 
 | // NOTE: To support shared resources an instance of this class will need to be | 
 | // shared by multiple GLES2Decoders. | 
 | class GPU_EXPORT BufferManager { | 
 |  public: | 
 |   BufferManager(MemoryTracker* memory_tracker, FeatureInfo* feature_info); | 
 |   ~BufferManager(); | 
 |  | 
 |   // Must call before destruction. | 
 |   void Destroy(bool have_context); | 
 |  | 
 |   // Creates a Buffer for the given buffer. | 
 |   void CreateBuffer(GLuint client_id, GLuint service_id); | 
 |  | 
 |   // Gets the buffer info for the given buffer. | 
 |   Buffer* GetBuffer(GLuint client_id); | 
 |  | 
 |   // Removes a buffer info for the given buffer. | 
 |   void RemoveBuffer(GLuint client_id); | 
 |  | 
 |   // Gets a client id for a given service id. | 
 |   bool GetClientId(GLuint service_id, GLuint* client_id) const; | 
 |  | 
 |   // Validates a glBufferSubData, and then calls DoBufferData if validation was | 
 |   // successful. | 
 |   void ValidateAndDoBufferSubData( | 
 |       ContextState* context_state, GLenum target, GLintptr offset, | 
 |       GLsizeiptr size, const GLvoid * data); | 
 |  | 
 |   // Validates a glBufferData, and then calls DoBufferData if validation was | 
 |   // successful. | 
 |   void ValidateAndDoBufferData( | 
 |     ContextState* context_state, GLenum target, GLsizeiptr size, | 
 |     const GLvoid * data, GLenum usage); | 
 |  | 
 |   // Validates a glGetBufferParameteriv, and then calls GetBufferParameteriv if | 
 |   // validation was successful. | 
 |   void ValidateAndDoGetBufferParameteriv( | 
 |     ContextState* context_state, GLenum target, GLenum pname, GLint* params); | 
 |  | 
 |   // Sets the target of a buffer. Returns false if the target can not be set. | 
 |   bool SetTarget(Buffer* buffer, GLenum target); | 
 |  | 
 |   void set_allow_buffers_on_multiple_targets(bool allow) { | 
 |     allow_buffers_on_multiple_targets_ = allow; | 
 |   } | 
 |  | 
 |   size_t mem_represented() const { | 
 |     return memory_tracker_->GetMemRepresented(); | 
 |   } | 
 |  | 
 |   // Tells for a given usage if this would be a client side array. | 
 |   bool IsUsageClientSideArray(GLenum usage); | 
 |  | 
 |   // Tells whether a buffer that is emulated using client-side arrays should be | 
 |   // set to a non-zero size. | 
 |   bool UseNonZeroSizeForClientSideArrayBuffer(); | 
 |  | 
 |  private: | 
 |   friend class Buffer; | 
 |   friend class TestHelper;  // Needs access to DoBufferData. | 
 |   friend class BufferManagerTestBase;  // Needs access to DoBufferSubData. | 
 |   void StartTracking(Buffer* buffer); | 
 |   void StopTracking(Buffer* buffer); | 
 |  | 
 |   Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target); | 
 |  | 
 |   // Does a glBufferSubData and updates the approriate accounting. | 
 |   // Assumes the values have already been validated. | 
 |   void DoBufferSubData( | 
 |       ErrorState* error_state, | 
 |       Buffer* buffer, | 
 |       GLintptr offset, | 
 |       GLsizeiptr size, | 
 |       const GLvoid* data); | 
 |  | 
 |   // Does a glBufferData and updates the approprate accounting. Currently | 
 |   // Assumes the values have already been validated. | 
 |   void DoBufferData( | 
 |       ErrorState* error_state, | 
 |       Buffer* buffer, | 
 |       GLsizeiptr size, | 
 |       GLenum usage, | 
 |       const GLvoid* data); | 
 |  | 
 |   // Sets the size, usage and initial data of a buffer. | 
 |   // If data is NULL buffer will be initialized to 0 if shadowed. | 
 |   void SetInfo( | 
 |       Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data); | 
 |  | 
 |   scoped_ptr<MemoryTypeTracker> memory_tracker_; | 
 |   scoped_refptr<FeatureInfo> feature_info_; | 
 |  | 
 |   // Info for each buffer in the system. | 
 |   typedef base::hash_map<GLuint, scoped_refptr<Buffer> > BufferMap; | 
 |   BufferMap buffers_; | 
 |  | 
 |   // Whether or not buffers can be bound to multiple targets. | 
 |   bool allow_buffers_on_multiple_targets_; | 
 |  | 
 |   // Counts the number of Buffer allocated with 'this' as its manager. | 
 |   // Allows to check no Buffer will outlive this. | 
 |   unsigned int buffer_count_; | 
 |  | 
 |   bool have_context_; | 
 |   bool use_client_side_arrays_for_stream_buffers_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(BufferManager); | 
 | }; | 
 |  | 
 | }  // namespace gles2 | 
 | }  // namespace gpu | 
 |  | 
 | #endif  // GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_ |