| Index: gpu/command_buffer/service/vertex_attrib_manager.cc
|
| diff --git a/gpu/command_buffer/service/vertex_attrib_manager.cc b/gpu/command_buffer/service/vertex_attrib_manager.cc
|
| index 50c2dec6b02b5e949dd0ca15d8dfcfe4ecfb595a..fe346ab04be09471b3c219c07fc90898002322bf 100644
|
| --- a/gpu/command_buffer/service/vertex_attrib_manager.cc
|
| +++ b/gpu/command_buffer/service/vertex_attrib_manager.cc
|
| @@ -9,13 +9,17 @@
|
| #include "base/command_line.h"
|
| #include "base/logging.h"
|
| #include "base/memory/scoped_ptr.h"
|
| +#include "base/string_number_conversions.h"
|
| #include "build/build_config.h"
|
| #define GLES2_GPU_SERVICE 1
|
| #include "gpu/command_buffer/common/gles2_cmd_format.h"
|
| #include "gpu/command_buffer/common/gles2_cmd_utils.h"
|
| #include "gpu/command_buffer/service/buffer_manager.h"
|
| +#include "gpu/command_buffer/service/feature_info.h"
|
| #include "gpu/command_buffer/service/gl_utils.h"
|
| +#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
|
| #include "gpu/command_buffer/service/gpu_switches.h"
|
| +#include "gpu/command_buffer/service/program_manager.h"
|
| #include "gpu/command_buffer/service/vertex_array_manager.h"
|
|
|
| namespace gpu {
|
| @@ -31,6 +35,7 @@ VertexAttrib::VertexAttrib()
|
| gl_stride_(0),
|
| real_stride_(16),
|
| divisor_(0),
|
| + is_client_side_array_(false),
|
| list_(NULL) {
|
| }
|
|
|
| @@ -154,5 +159,114 @@ void VertexAttribManager::Unbind(Buffer* buffer) {
|
| }
|
| }
|
|
|
| +bool VertexAttribManager::ValidateBindings(
|
| + const char* function_name,
|
| + GLES2Decoder* decoder,
|
| + FeatureInfo* feature_info,
|
| + Program* current_program,
|
| + GLuint max_vertex_accessed,
|
| + GLsizei primcount) {
|
| + // true if any enabled, used divisor is zero
|
| + bool divisor0 = false;
|
| + const GLuint kInitialBufferId = 0xFFFFFFFFU;
|
| + GLuint current_buffer_id = kInitialBufferId;
|
| + bool use_client_side_arrays_for_stream_buffers = feature_info->workarounds(
|
| + ).use_client_side_arrays_for_stream_buffers;
|
| + // Validate all attribs currently enabled. If they are used by the current
|
| + // program then check that they have enough elements to handle the draw call.
|
| + // If they are not used by the current program check that they have a buffer
|
| + // assigned.
|
| + for (VertexAttribInfoList::iterator it = enabled_vertex_attribs_.begin();
|
| + it != enabled_vertex_attribs_.end(); ++it) {
|
| + VertexAttrib* attrib = *it;
|
| + const Program::VertexAttrib* attrib_info =
|
| + current_program->GetAttribInfoByLocation(attrib->index());
|
| + if (attrib_info) {
|
| + divisor0 |= (attrib->divisor() == 0);
|
| + GLuint count = attrib->MaxVertexAccessed(primcount, max_vertex_accessed);
|
| + // This attrib is used in the current program.
|
| + if (!attrib->CanAccess(count)) {
|
| + decoder->SetGLError(
|
| + GL_INVALID_OPERATION, function_name,
|
| + (std::string(
|
| + "attempt to access out of range vertices in attribute ") +
|
| + base::IntToString(attrib->index())).c_str());
|
| + return false;
|
| + }
|
| + if (use_client_side_arrays_for_stream_buffers) {
|
| + Buffer* buffer = attrib->buffer();
|
| + glEnableVertexAttribArray(attrib->index());
|
| + if (buffer->IsClientSideArray()) {
|
| + if (current_buffer_id != 0) {
|
| + current_buffer_id = 0;
|
| + glBindBuffer(GL_ARRAY_BUFFER, 0);
|
| + }
|
| + attrib->set_is_client_side_array(true);
|
| + const void* ptr = buffer->GetRange(attrib->offset(), 0);
|
| + DCHECK(ptr);
|
| + glVertexAttribPointer(
|
| + attrib->index(),
|
| + attrib->size(),
|
| + attrib->type(),
|
| + attrib->normalized(),
|
| + attrib->gl_stride(),
|
| + ptr);
|
| + } else if (attrib->is_client_side_array()) {
|
| + attrib->set_is_client_side_array(false);
|
| + GLuint new_buffer_id = buffer->service_id();
|
| + if (new_buffer_id != current_buffer_id) {
|
| + current_buffer_id = new_buffer_id;
|
| + glBindBuffer(GL_ARRAY_BUFFER, current_buffer_id);
|
| + }
|
| + const void* ptr = reinterpret_cast<const void*>(attrib->offset());
|
| + glVertexAttribPointer(
|
| + attrib->index(),
|
| + attrib->size(),
|
| + attrib->type(),
|
| + attrib->normalized(),
|
| + attrib->gl_stride(),
|
| + ptr);
|
| + }
|
| + }
|
| + } else {
|
| + // This attrib is not used in the current program.
|
| + if (!attrib->buffer()) {
|
| + decoder->SetGLError(
|
| + GL_INVALID_OPERATION, function_name,
|
| + (std::string(
|
| + "attempt to render with no buffer attached to "
|
| + "enabled attribute ") +
|
| + base::IntToString(attrib->index())).c_str());
|
| + return false;
|
| + } else if (use_client_side_arrays_for_stream_buffers) {
|
| + Buffer* buffer = attrib->buffer();
|
| + // Disable client side arrays for unused attributes else we'll
|
| + // read bad memory
|
| + if (buffer->IsClientSideArray()) {
|
| + // Don't disable attrib 0 since it's special.
|
| + if (attrib->index() > 0) {
|
| + glDisableVertexAttribArray(attrib->index());
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (primcount && !divisor0) {
|
| + decoder->SetGLError(
|
| + GL_INVALID_OPERATION, function_name,
|
| + "attempt instanced render with all attributes having "
|
| + "non-zero divisors");
|
| + return false;
|
| + }
|
| +
|
| + if (current_buffer_id != kInitialBufferId) {
|
| + // Restore the buffer binding.
|
| + decoder->RestoreBufferBindings();
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| } // namespace gles2
|
| } // namespace gpu
|
|
|