| 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 |