OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/vertex_attrib_manager.h" | 5 #include "gpu/command_buffer/service/vertex_attrib_manager.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/string_number_conversions.h" | |
13 #include "build/build_config.h" | 12 #include "build/build_config.h" |
14 #define GLES2_GPU_SERVICE 1 | 13 #define GLES2_GPU_SERVICE 1 |
15 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 14 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
16 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 15 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
17 #include "gpu/command_buffer/service/buffer_manager.h" | 16 #include "gpu/command_buffer/service/buffer_manager.h" |
18 #include "gpu/command_buffer/service/feature_info.h" | |
19 #include "gpu/command_buffer/service/gl_utils.h" | 17 #include "gpu/command_buffer/service/gl_utils.h" |
20 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | |
21 #include "gpu/command_buffer/service/gpu_switches.h" | 18 #include "gpu/command_buffer/service/gpu_switches.h" |
22 #include "gpu/command_buffer/service/program_manager.h" | |
23 #include "gpu/command_buffer/service/vertex_array_manager.h" | 19 #include "gpu/command_buffer/service/vertex_array_manager.h" |
24 | 20 |
25 namespace gpu { | 21 namespace gpu { |
26 namespace gles2 { | 22 namespace gles2 { |
27 | 23 |
28 VertexAttrib::VertexAttrib() | 24 VertexAttrib::VertexAttrib() |
29 : index_(0), | 25 : index_(0), |
30 enabled_(false), | 26 enabled_(false), |
31 size_(4), | 27 size_(4), |
32 type_(GL_FLOAT), | 28 type_(GL_FLOAT), |
33 offset_(0), | 29 offset_(0), |
34 normalized_(GL_FALSE), | 30 normalized_(GL_FALSE), |
35 gl_stride_(0), | 31 gl_stride_(0), |
36 real_stride_(16), | 32 real_stride_(16), |
37 divisor_(0), | 33 divisor_(0), |
38 is_client_side_array_(false), | |
39 list_(NULL) { | 34 list_(NULL) { |
40 } | 35 } |
41 | 36 |
42 VertexAttrib::~VertexAttrib() { | 37 VertexAttrib::~VertexAttrib() { |
43 } | 38 } |
44 | 39 |
45 void VertexAttrib::SetInfo( | 40 void VertexAttrib::SetInfo( |
46 Buffer* buffer, | 41 Buffer* buffer, |
47 GLint size, | 42 GLint size, |
48 GLenum type, | 43 GLenum type, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 | 147 |
153 void VertexAttribManager::Unbind(Buffer* buffer) { | 148 void VertexAttribManager::Unbind(Buffer* buffer) { |
154 if (element_array_buffer_ == buffer) { | 149 if (element_array_buffer_ == buffer) { |
155 element_array_buffer_ = NULL; | 150 element_array_buffer_ = NULL; |
156 } | 151 } |
157 for (uint32 vv = 0; vv < vertex_attrib_infos_.size(); ++vv) { | 152 for (uint32 vv = 0; vv < vertex_attrib_infos_.size(); ++vv) { |
158 vertex_attrib_infos_[vv].Unbind(buffer); | 153 vertex_attrib_infos_[vv].Unbind(buffer); |
159 } | 154 } |
160 } | 155 } |
161 | 156 |
162 bool VertexAttribManager::ValidateBindings( | |
163 const char* function_name, | |
164 GLES2Decoder* decoder, | |
165 FeatureInfo* feature_info, | |
166 Program* current_program, | |
167 GLuint max_vertex_accessed, | |
168 GLsizei primcount) { | |
169 // true if any enabled, used divisor is zero | |
170 bool divisor0 = false; | |
171 const GLuint kInitialBufferId = 0xFFFFFFFFU; | |
172 GLuint current_buffer_id = kInitialBufferId; | |
173 bool use_client_side_arrays_for_stream_buffers = feature_info->workarounds( | |
174 ).use_client_side_arrays_for_stream_buffers; | |
175 // Validate all attribs currently enabled. If they are used by the current | |
176 // program then check that they have enough elements to handle the draw call. | |
177 // If they are not used by the current program check that they have a buffer | |
178 // assigned. | |
179 for (VertexAttribInfoList::iterator it = enabled_vertex_attribs_.begin(); | |
180 it != enabled_vertex_attribs_.end(); ++it) { | |
181 VertexAttrib* attrib = *it; | |
182 const Program::VertexAttrib* attrib_info = | |
183 current_program->GetAttribInfoByLocation(attrib->index()); | |
184 if (attrib_info) { | |
185 divisor0 |= (attrib->divisor() == 0); | |
186 GLuint count = attrib->MaxVertexAccessed(primcount, max_vertex_accessed); | |
187 // This attrib is used in the current program. | |
188 if (!attrib->CanAccess(count)) { | |
189 decoder->SetGLError( | |
190 GL_INVALID_OPERATION, function_name, | |
191 (std::string( | |
192 "attempt to access out of range vertices in attribute ") + | |
193 base::IntToString(attrib->index())).c_str()); | |
194 return false; | |
195 } | |
196 if (use_client_side_arrays_for_stream_buffers) { | |
197 Buffer* buffer = attrib->buffer(); | |
198 glEnableVertexAttribArray(attrib->index()); | |
199 if (buffer->IsClientSideArray()) { | |
200 if (current_buffer_id != 0) { | |
201 current_buffer_id = 0; | |
202 glBindBuffer(GL_ARRAY_BUFFER, 0); | |
203 } | |
204 attrib->set_is_client_side_array(true); | |
205 const void* ptr = buffer->GetRange(attrib->offset(), 0); | |
206 DCHECK(ptr); | |
207 glVertexAttribPointer( | |
208 attrib->index(), | |
209 attrib->size(), | |
210 attrib->type(), | |
211 attrib->normalized(), | |
212 attrib->gl_stride(), | |
213 ptr); | |
214 } else if (attrib->is_client_side_array()) { | |
215 attrib->set_is_client_side_array(false); | |
216 GLuint new_buffer_id = buffer->service_id(); | |
217 if (new_buffer_id != current_buffer_id) { | |
218 current_buffer_id = new_buffer_id; | |
219 glBindBuffer(GL_ARRAY_BUFFER, current_buffer_id); | |
220 } | |
221 const void* ptr = reinterpret_cast<const void*>(attrib->offset()); | |
222 glVertexAttribPointer( | |
223 attrib->index(), | |
224 attrib->size(), | |
225 attrib->type(), | |
226 attrib->normalized(), | |
227 attrib->gl_stride(), | |
228 ptr); | |
229 } | |
230 } | |
231 } else { | |
232 // This attrib is not used in the current program. | |
233 if (!attrib->buffer()) { | |
234 decoder->SetGLError( | |
235 GL_INVALID_OPERATION, function_name, | |
236 (std::string( | |
237 "attempt to render with no buffer attached to " | |
238 "enabled attribute ") + | |
239 base::IntToString(attrib->index())).c_str()); | |
240 return false; | |
241 } else if (use_client_side_arrays_for_stream_buffers) { | |
242 Buffer* buffer = attrib->buffer(); | |
243 // Disable client side arrays for unused attributes else we'll | |
244 // read bad memory | |
245 if (buffer->IsClientSideArray()) { | |
246 // Don't disable attrib 0 since it's special. | |
247 if (attrib->index() > 0) { | |
248 glDisableVertexAttribArray(attrib->index()); | |
249 } | |
250 } | |
251 } | |
252 } | |
253 } | |
254 | |
255 if (primcount && !divisor0) { | |
256 decoder->SetGLError( | |
257 GL_INVALID_OPERATION, function_name, | |
258 "attempt instanced render with all attributes having " | |
259 "non-zero divisors"); | |
260 return false; | |
261 } | |
262 | |
263 if (current_buffer_id != kInitialBufferId) { | |
264 // Restore the buffer binding. | |
265 decoder->RestoreBufferBindings(); | |
266 } | |
267 | |
268 return true; | |
269 } | |
270 | |
271 } // namespace gles2 | 157 } // namespace gles2 |
272 } // namespace gpu | 158 } // namespace gpu |
OLD | NEW |