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" |
12 #include "build/build_config.h" | 13 #include "build/build_config.h" |
13 #define GLES2_GPU_SERVICE 1 | 14 #define GLES2_GPU_SERVICE 1 |
14 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 15 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
15 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 16 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
16 #include "gpu/command_buffer/service/buffer_manager.h" | 17 #include "gpu/command_buffer/service/buffer_manager.h" |
| 18 #include "gpu/command_buffer/service/feature_info.h" |
17 #include "gpu/command_buffer/service/gl_utils.h" | 19 #include "gpu/command_buffer/service/gl_utils.h" |
| 20 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
18 #include "gpu/command_buffer/service/gpu_switches.h" | 21 #include "gpu/command_buffer/service/gpu_switches.h" |
| 22 #include "gpu/command_buffer/service/program_manager.h" |
19 #include "gpu/command_buffer/service/vertex_array_manager.h" | 23 #include "gpu/command_buffer/service/vertex_array_manager.h" |
20 | 24 |
21 namespace gpu { | 25 namespace gpu { |
22 namespace gles2 { | 26 namespace gles2 { |
23 | 27 |
24 VertexAttrib::VertexAttrib() | 28 VertexAttrib::VertexAttrib() |
25 : index_(0), | 29 : index_(0), |
26 enabled_(false), | 30 enabled_(false), |
27 size_(4), | 31 size_(4), |
28 type_(GL_FLOAT), | 32 type_(GL_FLOAT), |
29 offset_(0), | 33 offset_(0), |
30 normalized_(GL_FALSE), | 34 normalized_(GL_FALSE), |
31 gl_stride_(0), | 35 gl_stride_(0), |
32 real_stride_(16), | 36 real_stride_(16), |
33 divisor_(0), | 37 divisor_(0), |
| 38 is_client_side_array_(false), |
34 list_(NULL) { | 39 list_(NULL) { |
35 } | 40 } |
36 | 41 |
37 VertexAttrib::~VertexAttrib() { | 42 VertexAttrib::~VertexAttrib() { |
38 } | 43 } |
39 | 44 |
40 void VertexAttrib::SetInfo( | 45 void VertexAttrib::SetInfo( |
41 Buffer* buffer, | 46 Buffer* buffer, |
42 GLint size, | 47 GLint size, |
43 GLenum type, | 48 GLenum type, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 | 152 |
148 void VertexAttribManager::Unbind(Buffer* buffer) { | 153 void VertexAttribManager::Unbind(Buffer* buffer) { |
149 if (element_array_buffer_ == buffer) { | 154 if (element_array_buffer_ == buffer) { |
150 element_array_buffer_ = NULL; | 155 element_array_buffer_ = NULL; |
151 } | 156 } |
152 for (uint32 vv = 0; vv < vertex_attrib_infos_.size(); ++vv) { | 157 for (uint32 vv = 0; vv < vertex_attrib_infos_.size(); ++vv) { |
153 vertex_attrib_infos_[vv].Unbind(buffer); | 158 vertex_attrib_infos_[vv].Unbind(buffer); |
154 } | 159 } |
155 } | 160 } |
156 | 161 |
| 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 |
157 } // namespace gles2 | 271 } // namespace gles2 |
158 } // namespace gpu | 272 } // namespace gpu |
OLD | NEW |