blob: ea3fc0817ef1888e64609da794fc68e0454759dc [file]
// 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