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_VERTEX_ATTRIB_MANAGER_H_
6#define GPU_COMMAND_BUFFER_SERVICE_VERTEX_ATTRIB_MANAGER_H_
7
8#include <list>
9#include <vector>
10#include "base/logging.h"
11#include "base/memory/ref_counted.h"
12#include "build/build_config.h"
13#include "gpu/command_buffer/service/buffer_manager.h"
14#include "gpu/command_buffer/service/gl_utils.h"
15#include "gpu/gpu_export.h"
16
17namespace gpu {
18namespace gles2 {
19
20class FeatureInfo;
21class GLES2Decoder;
22class Program;
23class VertexArrayManager;
24
25// Info about a Vertex Attribute. This is used to track what the user currently
26// has bound on each Vertex Attribute so that checking can be done at
27// glDrawXXX time.
28class GPU_EXPORT VertexAttrib {
29 public:
30  typedef std::list<VertexAttrib*> VertexAttribList;
31
32  VertexAttrib();
33  ~VertexAttrib();
34
35  // Returns true if this VertexAttrib can access index.
36  bool CanAccess(GLuint index) const;
37
38  Buffer* buffer() const { return buffer_.get(); }
39
40  GLsizei offset() const {
41    return offset_;
42  }
43
44  GLuint index() const {
45    return index_;
46  }
47
48  GLint size() const {
49    return size_;
50  }
51
52  GLenum type() const {
53    return type_;
54  }
55
56  GLboolean normalized() const {
57    return normalized_;
58  }
59
60  GLsizei gl_stride() const {
61    return gl_stride_;
62  }
63
64  GLuint divisor() const {
65    return divisor_;
66  }
67
68  bool enabled() const {
69    return enabled_;
70  }
71
72  // Find the maximum vertex accessed, accounting for instancing.
73  GLuint MaxVertexAccessed(GLsizei primcount,
74                           GLuint max_vertex_accessed) const {
75    return divisor_ ? ((primcount - 1) / divisor_) : max_vertex_accessed;
76  }
77
78  bool is_client_side_array() const {
79    return is_client_side_array_;
80  }
81
82  void set_is_client_side_array(bool value) {
83    is_client_side_array_ = value;
84  }
85
86 private:
87  friend class VertexAttribManager;
88
89  void set_enabled(bool enabled) {
90    enabled_ = enabled;
91  }
92
93  void set_index(GLuint index) {
94    index_ = index;
95  }
96
97  void SetList(VertexAttribList* new_list) {
98    DCHECK(new_list);
99
100    if (list_) {
101      list_->erase(it_);
102    }
103
104    it_ = new_list->insert(new_list->end(), this);
105    list_ = new_list;
106  }
107
108  void SetInfo(
109      Buffer* buffer,
110      GLint size,
111      GLenum type,
112      GLboolean normalized,
113      GLsizei gl_stride,
114      GLsizei real_stride,
115      GLsizei offset);
116
117  void SetDivisor(GLsizei divisor) {
118    divisor_ = divisor;
119  }
120
121  void Unbind(Buffer* buffer);
122
123  // The index of this attrib.
124  GLuint index_;
125
126  // Whether or not this attribute is enabled.
127  bool enabled_;
128
129  // number of components (1, 2, 3, 4)
130  GLint size_;
131
132  // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
133  GLenum type_;
134
135  // The offset into the buffer.
136  GLsizei offset_;
137
138  GLboolean normalized_;
139
140  // The stride passed to glVertexAttribPointer.
141  GLsizei gl_stride_;
142
143  // The stride that will be used to access the buffer. This is the actual
144  // stide, NOT the GL bogus stride. In other words there is never a stride
145  // of 0.
146  GLsizei real_stride_;
147
148  GLsizei divisor_;
149
150  // Will be true if this was assigned to a client side array.
151  bool is_client_side_array_;
152
153  // The buffer bound to this attribute.
154  scoped_refptr<Buffer> buffer_;
155
156  // List this info is on.
157  VertexAttribList* list_;
158
159  // Iterator for list this info is on. Enabled/Disabled
160  VertexAttribList::iterator it_;
161};
162
163// Manages vertex attributes.
164// This class also acts as the service-side representation of a
165// vertex array object and it's contained state.
166class GPU_EXPORT VertexAttribManager :
167    public base::RefCounted<VertexAttribManager> {
168 public:
169  typedef std::list<VertexAttrib*> VertexAttribList;
170
171  VertexAttribManager();
172
173  void Initialize(uint32 num_vertex_attribs, bool init_attribs);
174
175  bool Enable(GLuint index, bool enable);
176
177  bool HaveFixedAttribs() const {
178    return num_fixed_attribs_ != 0;
179  }
180
181  const VertexAttribList& GetEnabledVertexAttribs() const {
182    return enabled_vertex_attribs_;
183  }
184
185  VertexAttrib* GetVertexAttrib(GLuint index) {
186    if (index < vertex_attribs_.size()) {
187      return &vertex_attribs_[index];
188    }
189    return NULL;
190  }
191
192  void SetAttribInfo(
193      GLuint index,
194      Buffer* buffer,
195      GLint size,
196      GLenum type,
197      GLboolean normalized,
198      GLsizei gl_stride,
199      GLsizei real_stride,
200      GLsizei offset) {
201    VertexAttrib* attrib = GetVertexAttrib(index);
202    if (attrib) {
203      if (attrib->type() == GL_FIXED) {
204        --num_fixed_attribs_;
205      }
206      if (type == GL_FIXED) {
207        ++num_fixed_attribs_;
208      }
209      attrib->SetInfo(
210          buffer, size, type, normalized, gl_stride, real_stride, offset);
211    }
212  }
213
214  void SetDivisor(GLuint index, GLuint divisor) {
215    VertexAttrib* attrib = GetVertexAttrib(index);
216    if (attrib) {
217      attrib->SetDivisor(divisor);
218    }
219  }
220
221  void SetElementArrayBuffer(Buffer* buffer);
222
223  Buffer* element_array_buffer() const { return element_array_buffer_.get(); }
224
225  GLuint service_id() const {
226    return service_id_;
227  }
228
229  void Unbind(Buffer* buffer);
230
231  bool IsDeleted() const {
232    return deleted_;
233  }
234
235  bool IsValid() const {
236    return !IsDeleted();
237  }
238
239  size_t num_attribs() const {
240    return vertex_attribs_.size();
241  }
242
243  bool ValidateBindings(
244      const char* function_name,
245      GLES2Decoder* decoder,
246      FeatureInfo* feature_info,
247      Program* current_program,
248      GLuint max_vertex_accessed,
249      bool instanced,
250      GLsizei primcount);
251
252 private:
253  friend class VertexArrayManager;
254  friend class VertexArrayManagerTest;
255  friend class base::RefCounted<VertexAttribManager>;
256
257  // Used when creating from a VertexArrayManager
258  VertexAttribManager(VertexArrayManager* manager, GLuint service_id,
259      uint32 num_vertex_attribs);
260
261  ~VertexAttribManager();
262
263  void MarkAsDeleted() {
264    deleted_ = true;
265  }
266
267  // number of attribs using type GL_FIXED.
268  int num_fixed_attribs_;
269
270  // Info for each vertex attribute saved so we can check at glDrawXXX time
271  // if it is safe to draw.
272  std::vector<VertexAttrib> vertex_attribs_;
273
274  // The currently bound element array buffer. If this is 0 it is illegal
275  // to call glDrawElements.
276  scoped_refptr<Buffer> element_array_buffer_;
277
278  // Lists for which vertex attribs are enabled, disabled.
279  VertexAttribList enabled_vertex_attribs_;
280  VertexAttribList disabled_vertex_attribs_;
281
282  // The VertexArrayManager that owns this VertexAttribManager
283  VertexArrayManager* manager_;
284
285  // True if deleted.
286  bool deleted_;
287
288  // Service side vertex array object id.
289  GLuint service_id_;
290};
291
292}  // namespace gles2
293}  // namespace gpu
294
295#endif  // GPU_COMMAND_BUFFER_SERVICE_VERTEX_ATTRIB_MANAGER_H_
296
297