// Copyright 2015 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 "modules/webgl/WebGLVertexArrayObjectBase.h"

#include "gpu/command_buffer/client/gles2_interface.h"
#include "modules/webgl/WebGLRenderingContextBase.h"

namespace blink {

WebGLVertexArrayObjectBase::WebGLVertexArrayObjectBase(
    WebGLRenderingContextBase* ctx,
    VaoType type)
    : WebGLContextObject(ctx),
      m_object(0),
      m_type(type),
      m_hasEverBeenBound(false),
      m_boundElementArrayBuffer(this, nullptr),
      m_isAllEnabledAttribBufferBound(true) {
  m_arrayBufferList.resize(ctx->maxVertexAttribs());
  m_attribEnabled.resize(ctx->maxVertexAttribs());
  for (size_t i = 0; i < m_attribEnabled.size(); ++i) {
    m_attribEnabled[i] = false;
  }

  switch (m_type) {
    case VaoTypeDefault:
      break;
    default:
      context()->contextGL()->GenVertexArraysOES(1, &m_object);
      break;
  }
}

WebGLVertexArrayObjectBase::~WebGLVertexArrayObjectBase() {
  runDestructor();
}

void WebGLVertexArrayObjectBase::dispatchDetached(
    gpu::gles2::GLES2Interface* gl) {
  if (m_boundElementArrayBuffer)
    m_boundElementArrayBuffer->onDetached(gl);

  for (size_t i = 0; i < m_arrayBufferList.size(); ++i) {
    if (m_arrayBufferList[i])
      m_arrayBufferList[i]->onDetached(gl);
  }
}

void WebGLVertexArrayObjectBase::deleteObjectImpl(
    gpu::gles2::GLES2Interface* gl) {
  switch (m_type) {
    case VaoTypeDefault:
      break;
    default:
      gl->DeleteVertexArraysOES(1, &m_object);
      m_object = 0;
      break;
  }

  // Member<> objects must not be accessed during the destruction,
  // since they could have been already finalized.
  // The finalizers of these objects will handle their detachment
  // by themselves.
  if (!destructionInProgress())
    dispatchDetached(gl);
}

void WebGLVertexArrayObjectBase::setElementArrayBuffer(WebGLBuffer* buffer) {
  if (buffer)
    buffer->onAttached();
  if (m_boundElementArrayBuffer)
    m_boundElementArrayBuffer->onDetached(context()->contextGL());
  m_boundElementArrayBuffer = buffer;
}

WebGLBuffer* WebGLVertexArrayObjectBase::getArrayBufferForAttrib(size_t index) {
  DCHECK(index < context()->maxVertexAttribs());
  return m_arrayBufferList[index].get();
}

void WebGLVertexArrayObjectBase::setArrayBufferForAttrib(GLuint index,
                                                         WebGLBuffer* buffer) {
  if (buffer)
    buffer->onAttached();
  if (m_arrayBufferList[index])
    m_arrayBufferList[index]->onDetached(context()->contextGL());

  m_arrayBufferList[index] = TraceWrapperMember<WebGLBuffer>(this, buffer);
  updateAttribBufferBoundStatus();
}

void WebGLVertexArrayObjectBase::setAttribEnabled(GLuint index, bool enabled) {
  DCHECK(index < context()->maxVertexAttribs());
  m_attribEnabled[index] = enabled;
  updateAttribBufferBoundStatus();
}

bool WebGLVertexArrayObjectBase::getAttribEnabled(GLuint index) const {
  DCHECK(index < context()->maxVertexAttribs());
  return m_attribEnabled[index];
}

void WebGLVertexArrayObjectBase::updateAttribBufferBoundStatus() {
  m_isAllEnabledAttribBufferBound = true;
  for (size_t i = 0; i < m_attribEnabled.size(); ++i) {
    if (m_attribEnabled[i] && !m_arrayBufferList[i]) {
      m_isAllEnabledAttribBufferBound = false;
      return;
    }
  }
}

void WebGLVertexArrayObjectBase::unbindBuffer(WebGLBuffer* buffer) {
  if (m_boundElementArrayBuffer == buffer) {
    m_boundElementArrayBuffer->onDetached(context()->contextGL());
    m_boundElementArrayBuffer = nullptr;
  }

  for (size_t i = 0; i < m_arrayBufferList.size(); ++i) {
    if (m_arrayBufferList[i] == buffer) {
      m_arrayBufferList[i]->onDetached(context()->contextGL());
      m_arrayBufferList[i] = nullptr;
    }
  }
  updateAttribBufferBoundStatus();
}

void WebGLVertexArrayObjectBase::visitChildDOMWrappers(
    v8::Isolate* isolate,
    const v8::Persistent<v8::Object>& wrapper) {
  DOMWrapperWorld::setWrapperReferencesInAllWorlds(
      wrapper, m_boundElementArrayBuffer, isolate);
  for (size_t i = 0; i < m_arrayBufferList.size(); ++i) {
    DOMWrapperWorld::setWrapperReferencesInAllWorlds(
        wrapper, m_arrayBufferList[i], isolate);
  }
}

DEFINE_TRACE(WebGLVertexArrayObjectBase) {
  visitor->trace(m_boundElementArrayBuffer);
  visitor->trace(m_arrayBufferList);
  WebGLContextObject::trace(visitor);
}

DEFINE_TRACE_WRAPPERS(WebGLVertexArrayObjectBase) {
  visitor->traceWrappers(m_boundElementArrayBuffer);
  for (size_t i = 0; i < m_arrayBufferList.size(); ++i) {
    visitor->traceWrappers(m_arrayBufferList[i]);
  }
  WebGLContextObject::traceWrappers(visitor);
}

}  // namespace blink
