// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/service/vertex_attrib_manager.h"

#include <stdint.h>

#include <list>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#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/error_state.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 {
namespace gles2 {

VertexAttrib::VertexAttrib()
    : index_(0),
      enabled_(false),
      enabled_in_driver_(false),
      size_(4),
      type_(GL_FLOAT),
      offset_(0),
      normalized_(GL_FALSE),
      gl_stride_(0),
      real_stride_(16),
      divisor_(0),
      integer_(GL_FALSE),
      is_client_side_array_(false),
      list_(nullptr) {}

VertexAttrib::VertexAttrib(const VertexAttrib& other) = default;

VertexAttrib::~VertexAttrib() = default;

void VertexAttrib::SetInfo(
    Buffer* buffer,
    GLint size,
    GLenum type,
    GLboolean normalized,
    GLsizei gl_stride,
    GLsizei real_stride,
    GLsizei offset,
    GLboolean integer) {
  DCHECK_GT(real_stride, 0);
  buffer_ = buffer;
  size_ = size;
  type_ = type;
  normalized_ = normalized;
  gl_stride_ = gl_stride;
  real_stride_ = real_stride;
  offset_ = offset;
  integer_ = integer;
}

bool VertexAttrib::CanAccess(GLuint index) const {
  if (!enabled_) {
    return true;
  }

  DCHECK(buffer_.get() && !buffer_->IsDeleted());
  // The number of elements that can be accessed.
  GLsizeiptr buffer_size = buffer_->size();
  if (offset_ > buffer_size || real_stride_ == 0) {
    return false;
  }

  uint32_t usable_size = buffer_size - offset_;
  GLuint num_elements = usable_size / real_stride_ +
      ((usable_size % real_stride_) >=
       (GLES2Util::GetGroupSizeForBufferType(size_, type_)) ? 1 : 0);
  return index < num_elements;
}

VertexAttribManager::VertexAttribManager(bool do_buffer_refcounting)
    : num_fixed_attribs_(0),
      element_array_buffer_(nullptr),
      manager_(nullptr),
      deleted_(false),
      is_bound_(false),
      do_buffer_refcounting_(do_buffer_refcounting),
      service_id_(0) {}

VertexAttribManager::VertexAttribManager(VertexArrayManager* manager,
                                         GLuint service_id,
                                         uint32_t num_vertex_attribs,
                                         bool do_buffer_refcounting)
    : num_fixed_attribs_(0),
      element_array_buffer_(nullptr),
      manager_(manager),
      deleted_(false),
      is_bound_(false),
      do_buffer_refcounting_(do_buffer_refcounting),
      service_id_(service_id) {
  manager_->StartTracking(this);
  Initialize(num_vertex_attribs, false);
}

VertexAttribManager::~VertexAttribManager() {
  if (manager_) {
    if (manager_->have_context_) {
      if (service_id_ != 0)  // 0 indicates an emulated VAO
        glDeleteVertexArraysOES(1, &service_id_);
    }
    manager_->StopTracking(this);
    manager_ = nullptr;
  }
}

void VertexAttribManager::Initialize(uint32_t max_vertex_attribs,
                                     bool init_attribs) {
  vertex_attribs_.resize(max_vertex_attribs);
  uint32_t packed_size = (max_vertex_attribs + 15) / 16;
  attrib_base_type_mask_.resize(packed_size);
  attrib_enabled_mask_.resize(packed_size);

  for (uint32_t ii = 0; ii < packed_size; ++ii) {
    attrib_enabled_mask_[ii] = 0u;
    attrib_base_type_mask_[ii] = 0u;
  }

  for (uint32_t vv = 0; vv < vertex_attribs_.size(); ++vv) {
    vertex_attribs_[vv].set_index(vv);
    vertex_attribs_[vv].SetList(&disabled_vertex_attribs_);

    if (init_attribs) {
      glVertexAttrib4f(vv, 0.0f, 0.0f, 0.0f, 1.0f);
    }
  }
}

void VertexAttribManager::SetElementArrayBuffer(Buffer* buffer) {
  if (do_buffer_refcounting_ && is_bound_ && element_array_buffer_)
    element_array_buffer_->OnUnbind(GL_ELEMENT_ARRAY_BUFFER, false);
  element_array_buffer_ = buffer;
  if (do_buffer_refcounting_ && is_bound_ && buffer)
    buffer->OnBind(GL_ELEMENT_ARRAY_BUFFER, false);
}

bool VertexAttribManager::Enable(GLuint index, bool enable) {
  if (index >= vertex_attribs_.size()) {
    return false;
  }

  VertexAttrib& info = vertex_attribs_[index];
  if (info.enabled() != enable) {
    info.set_enabled(enable);
    info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
    GLuint shift_bits = (index % 16) * 2;
    if (enable) {
      attrib_enabled_mask_[index / 16] |= (0x3 << shift_bits);
    } else {
      attrib_enabled_mask_[index / 16] &= ~(0x3 << shift_bits);
    }
  }
  return true;
}

void VertexAttribManager::Unbind(Buffer* buffer, Buffer* bound_array_buffer) {
  DCHECK(buffer);
  DCHECK(is_bound_);
  if (element_array_buffer_.get() == buffer) {
    if (do_buffer_refcounting_)
      buffer->OnUnbind(GL_ELEMENT_ARRAY_BUFFER, false);
    if (manager_ && manager_->have_context_)
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    element_array_buffer_ = nullptr;
  }
  // When a vertex array object is bound, some drivers (AMD Linux,
  // Qualcomm, etc.) have a bug where it incorrectly generates an
  // GL_INVALID_OPERATION on glVertexAttribPointer() if pointer is
  // NULL, no buffer is bound on GL_ARRAY_BUFFER.  Therefore, in order
  // to clear the buffer bindings, we create a new array buffer,
  // redirect all bindings to the new buffer, and then delete the
  // buffer.
  GLuint new_buffer = 0;
  for (uint32_t vv = 0; vv < vertex_attribs_.size(); ++vv) {
    if (vertex_attribs_[vv].buffer_ == buffer) {
      if (do_buffer_refcounting_)
        buffer->OnUnbind(GL_ARRAY_BUFFER, true);
      vertex_attribs_[vv].buffer_ = nullptr;
      if (manager_ && manager_->have_context_) {
        if (!new_buffer) {
          glGenBuffersARB(1, &new_buffer);
          DCHECK_NE(0u, new_buffer);
          glBindBuffer(GL_ARRAY_BUFFER, new_buffer);
          // TODO(zmo): Do we need to also call glBufferData() here?
        }
        glVertexAttribPointer(
            vv, vertex_attribs_[vv].size_, vertex_attribs_[vv].type_,
            vertex_attribs_[vv].normalized_, vertex_attribs_[vv].gl_stride_, 0);
      }
    }
  }
  if (new_buffer) {
    glDeleteBuffersARB(1, &new_buffer);
    glBindBuffer(GL_ARRAY_BUFFER,
                 bound_array_buffer ? bound_array_buffer->service_id() : 0u);
  }
}

void VertexAttribManager::SetIsBound(bool is_bound) {
  if (is_bound == is_bound_)
    return;
  is_bound_ = is_bound;
  if (do_buffer_refcounting_) {
    if (element_array_buffer_) {
      if (is_bound)
        element_array_buffer_->OnBind(GL_ELEMENT_ARRAY_BUFFER, false);
      else
        element_array_buffer_->OnUnbind(GL_ELEMENT_ARRAY_BUFFER, false);
    }
    for (const auto& va : vertex_attribs_) {
      if (va.buffer_) {
        if (is_bound) {
          va.buffer_->OnBind(GL_ARRAY_BUFFER, true);
        } else {
          va.buffer_->OnUnbind(GL_ARRAY_BUFFER, true);
        }
      }
    }
  }
}

bool VertexAttribManager::ValidateBindings(
    const char* function_name,
    GLES2Decoder* decoder,
    FeatureInfo* feature_info,
    BufferManager* buffer_manager,
    Program* current_program,
    GLuint max_vertex_accessed,
    bool instanced,
    GLsizei primcount) {
  DCHECK(primcount);
  ErrorState* error_state = decoder->GetErrorState();
  // true if any enabled, used divisor is zero
  bool divisor0 = false;
  bool have_enabled_active_attribs = 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 (VertexAttribList::iterator it = enabled_vertex_attribs_.begin();
       it != enabled_vertex_attribs_.end(); ++it) {
    VertexAttrib* attrib = *it;
    Buffer* buffer = attrib->buffer();
    if (!buffer_manager->RequestBufferAccess(error_state, buffer, function_name,
                                             "attached to enabled attrib %u",
                                             attrib->index())) {
      return false;
    }
    const Program::VertexAttrib* attrib_info =
        current_program->GetAttribInfoByLocation(attrib->index());

    // Make sure that every attrib in enabled_vertex_attribs_ is really enabled
    // in the driver, if AND ONLY IF it is consumed by the current shader
    // program. (Note that since the containing loop is over
    // enabled_vertex_attribs_, not all vertex attribs, it doesn't erroneously
    // enable any attribs that should be disabled.)
    // This is for http://crbug.com/756293 but also subsumes some workaround
    // code for use_client_side_arrays_for_stream_buffers.
    SetDriverVertexAttribEnabled(attrib->index(), attrib_info != nullptr);

    if (attrib_info) {
      divisor0 |= (attrib->divisor() == 0);
      have_enabled_active_attribs = true;
      GLuint count = attrib->MaxVertexAccessed(primcount, max_vertex_accessed);
      // This attrib is used in the current program.
      if (!attrib->CanAccess(count)) {
        ERRORSTATE_SET_GL_ERROR(
            error_state, GL_INVALID_OPERATION, function_name,
            (std::string(
                "attempt to access out of range vertices in attribute ") +
             base::UintToString(attrib->index())).c_str());
        return false;
      }
      if (use_client_side_arrays_for_stream_buffers) {
        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);
        }
      }
    }
  }

  // Due to D3D9 limitation, in ES2/WebGL1, instanced drawing needs at least
  // one enabled attribute with divisor zero. This does not apply to D3D11,
  // therefore, it also does not apply to ES3/WebGL2.
  // Non-instanced drawing is fine with having no attributes at all, but if
  // there are attributes, at least one should have divisor zero.
  // (See ANGLE_instanced_arrays spec)
  if (feature_info->IsWebGL1OrES2Context() && !divisor0 &&
      (instanced || have_enabled_active_attribs)) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_OPERATION, function_name,
        "attempt to draw 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
