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.
4
5#ifndef GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
6#define GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
7
8#include <map>
9#include "base/basictypes.h"
10#include "base/containers/hash_tables.h"
11#include "base/logging.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "gpu/command_buffer/service/gl_utils.h"
15#include "gpu/command_buffer/service/memory_tracking.h"
16#include "gpu/gpu_export.h"
17
18namespace gpu {
19namespace gles2 {
20
21class BufferManager;
22struct ContextState;
23class ErrorState;
24class FeatureInfo;
25class TestHelper;
26
27// Info about Buffers currently in the system.
28class GPU_EXPORT Buffer : public base::RefCounted<Buffer> {
29 public:
30  Buffer(BufferManager* manager, GLuint service_id);
31
32  GLuint service_id() const {
33    return service_id_;
34  }
35
36  GLenum target() const {
37    return target_;
38  }
39
40  GLsizeiptr size() const {
41    return size_;
42  }
43
44  GLenum usage() const {
45    return usage_;
46  }
47
48  // Gets the maximum value in the buffer for the given range interpreted as
49  // the given type. Returns false if offset and count are out of range.
50  // offset is in bytes.
51  // count is in elements of type.
52  bool GetMaxValueForRange(GLuint offset, GLsizei count, GLenum type,
53                           GLuint* max_value);
54
55  // Returns a pointer to shadowed data.
56  const void* GetRange(GLintptr offset, GLsizeiptr size) const;
57
58  bool IsDeleted() const {
59    return deleted_;
60  }
61
62  bool IsValid() const {
63    return target() && !IsDeleted();
64  }
65
66  bool IsClientSideArray() const {
67    return is_client_side_array_;
68  }
69
70 private:
71  friend class BufferManager;
72  friend class BufferManagerTestBase;
73  friend class base::RefCounted<Buffer>;
74
75  // Represents a range in a buffer.
76  class Range {
77   public:
78    Range(GLuint offset, GLsizei count, GLenum type)
79        : offset_(offset),
80          count_(count),
81          type_(type) {
82    }
83
84    // A less functor provided for std::map so it can find ranges.
85    struct Less {
86      bool operator() (const Range& lhs, const Range& rhs) const {
87        if (lhs.offset_ != rhs.offset_) {
88          return lhs.offset_ < rhs.offset_;
89        }
90        if (lhs.count_ != rhs.count_) {
91          return lhs.count_ < rhs.count_;
92        }
93        return lhs.type_ < rhs.type_;
94      }
95    };
96
97   private:
98    GLuint offset_;
99    GLsizei count_;
100    GLenum type_;
101  };
102
103  ~Buffer();
104
105  void set_target(GLenum target) {
106    DCHECK_EQ(target_, 0u);  // you can only set this once.
107    target_ = target;
108  }
109
110  bool shadowed() const {
111    return shadowed_;
112  }
113
114  void MarkAsDeleted() {
115    deleted_ = true;
116  }
117
118  // Sets the size, usage and initial data of a buffer.
119  // If shadow is true then if data is NULL buffer will be initialized to 0.
120  void SetInfo(
121      GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data,
122      bool is_client_side_array);
123
124  // Sets a range of data for this buffer. Returns false if the offset or size
125  // is out of range.
126  bool SetRange(
127    GLintptr offset, GLsizeiptr size, const GLvoid * data);
128
129  // Clears any cache of index ranges.
130  void ClearCache();
131
132  // Check if an offset, size range is valid for the current buffer.
133  bool CheckRange(GLintptr offset, GLsizeiptr size) const;
134
135  // The manager that owns this Buffer.
136  BufferManager* manager_;
137
138  // A copy of the data in the buffer. This data is only kept if the target
139  // is backed_ = true.
140  scoped_ptr<int8[]> shadow_;
141
142  // Size of buffer.
143  GLsizeiptr size_;
144
145  // True if deleted.
146  bool deleted_;
147
148  // Whether or not the data is shadowed.
149  bool shadowed_;
150
151  // Whether or not this Buffer is not uploaded to the GPU but just
152  // sitting in local memory.
153  bool is_client_side_array_;
154
155  // Service side buffer id.
156  GLuint service_id_;
157
158  // The type of buffer. 0 = unset, GL_BUFFER_ARRAY = vertex data,
159  // GL_ELEMENT_BUFFER_ARRAY = index data.
160  // Once set a buffer can not be used for something else.
161  GLenum target_;
162
163  // Usage of buffer.
164  GLenum usage_;
165
166  // A map of ranges to the highest value in that range of a certain type.
167  typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap;
168  RangeToMaxValueMap range_set_;
169};
170
171// This class keeps track of the buffers and their sizes so we can do
172// bounds checking.
173//
174// NOTE: To support shared resources an instance of this class will need to be
175// shared by multiple GLES2Decoders.
176class GPU_EXPORT BufferManager {
177 public:
178  BufferManager(MemoryTracker* memory_tracker, FeatureInfo* feature_info);
179  ~BufferManager();
180
181  // Must call before destruction.
182  void Destroy(bool have_context);
183
184  // Creates a Buffer for the given buffer.
185  void CreateBuffer(GLuint client_id, GLuint service_id);
186
187  // Gets the buffer info for the given buffer.
188  Buffer* GetBuffer(GLuint client_id);
189
190  // Removes a buffer info for the given buffer.
191  void RemoveBuffer(GLuint client_id);
192
193  // Gets a client id for a given service id.
194  bool GetClientId(GLuint service_id, GLuint* client_id) const;
195
196  // Validates a glBufferSubData, and then calls DoBufferData if validation was
197  // successful.
198  void ValidateAndDoBufferSubData(
199      ContextState* context_state, GLenum target, GLintptr offset,
200      GLsizeiptr size, const GLvoid * data);
201
202  // Validates a glBufferData, and then calls DoBufferData if validation was
203  // successful.
204  void ValidateAndDoBufferData(
205    ContextState* context_state, GLenum target, GLsizeiptr size,
206    const GLvoid * data, GLenum usage);
207
208  // Validates a glGetBufferParameteriv, and then calls GetBufferParameteriv if
209  // validation was successful.
210  void ValidateAndDoGetBufferParameteriv(
211    ContextState* context_state, GLenum target, GLenum pname, GLint* params);
212
213  // Sets the target of a buffer. Returns false if the target can not be set.
214  bool SetTarget(Buffer* buffer, GLenum target);
215
216  void set_allow_buffers_on_multiple_targets(bool allow) {
217    allow_buffers_on_multiple_targets_ = allow;
218  }
219
220  size_t mem_represented() const {
221    return memory_tracker_->GetMemRepresented();
222  }
223
224  // Tells for a given usage if this would be a client side array.
225  bool IsUsageClientSideArray(GLenum usage);
226
227  // Tells whether a buffer that is emulated using client-side arrays should be
228  // set to a non-zero size.
229  bool UseNonZeroSizeForClientSideArrayBuffer();
230
231 private:
232  friend class Buffer;
233  friend class TestHelper;  // Needs access to DoBufferData.
234  friend class BufferManagerTestBase;  // Needs access to DoBufferSubData.
235  void StartTracking(Buffer* buffer);
236  void StopTracking(Buffer* buffer);
237
238  Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target);
239
240  // Does a glBufferSubData and updates the approriate accounting.
241  // Assumes the values have already been validated.
242  void DoBufferSubData(
243      ErrorState* error_state,
244      Buffer* buffer,
245      GLintptr offset,
246      GLsizeiptr size,
247      const GLvoid* data);
248
249  // Does a glBufferData and updates the approprate accounting. Currently
250  // Assumes the values have already been validated.
251  void DoBufferData(
252      ErrorState* error_state,
253      Buffer* buffer,
254      GLsizeiptr size,
255      GLenum usage,
256      const GLvoid* data);
257
258  // Sets the size, usage and initial data of a buffer.
259  // If data is NULL buffer will be initialized to 0 if shadowed.
260  void SetInfo(
261      Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data);
262
263  scoped_ptr<MemoryTypeTracker> memory_tracker_;
264  scoped_refptr<FeatureInfo> feature_info_;
265
266  // Info for each buffer in the system.
267  typedef base::hash_map<GLuint, scoped_refptr<Buffer> > BufferMap;
268  BufferMap buffers_;
269
270  // Whether or not buffers can be bound to multiple targets.
271  bool allow_buffers_on_multiple_targets_;
272
273  // Counts the number of Buffer allocated with 'this' as its manager.
274  // Allows to check no Buffer will outlive this.
275  unsigned int buffer_count_;
276
277  bool have_context_;
278  bool use_client_side_arrays_for_stream_buffers_;
279
280  DISALLOW_COPY_AND_ASSIGN(BufferManager);
281};
282
283}  // namespace gles2
284}  // namespace gpu
285
286#endif  // GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
287