blob: 61135789a0ff7acaa239d1eaeb46613698f373d2 [file] [log] [blame]
// 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 "third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
namespace blink {
WebGLVertexArrayObjectBase::WebGLVertexArrayObjectBase(
WebGLRenderingContextBase* ctx,
VaoType type)
: WebGLContextObject(ctx),
object_(0),
type_(type),
has_ever_been_bound_(false),
is_all_enabled_attrib_buffer_bound_(true) {
array_buffer_list_.resize(ctx->MaxVertexAttribs());
attrib_enabled_.resize(ctx->MaxVertexAttribs());
for (wtf_size_t i = 0; i < attrib_enabled_.size(); ++i) {
attrib_enabled_[i] = false;
}
switch (type_) {
case kVaoTypeDefault:
break;
default:
Context()->ContextGL()->GenVertexArraysOES(1, &object_);
break;
}
}
WebGLVertexArrayObjectBase::~WebGLVertexArrayObjectBase() {
RunDestructor();
}
void WebGLVertexArrayObjectBase::DispatchDetached(
gpu::gles2::GLES2Interface* gl) {
if (bound_element_array_buffer_)
bound_element_array_buffer_->OnDetached(gl);
for (WebGLBuffer* buffer : array_buffer_list_) {
if (buffer)
buffer->OnDetached(gl);
}
}
void WebGLVertexArrayObjectBase::DeleteObjectImpl(
gpu::gles2::GLES2Interface* gl) {
switch (type_) {
case kVaoTypeDefault:
break;
default:
gl->DeleteVertexArraysOES(1, &object_);
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 (bound_element_array_buffer_)
bound_element_array_buffer_->OnDetached(Context()->ContextGL());
bound_element_array_buffer_ = buffer;
}
WebGLBuffer* WebGLVertexArrayObjectBase::GetArrayBufferForAttrib(GLuint index) {
DCHECK(index < Context()->MaxVertexAttribs());
return array_buffer_list_[index].Get();
}
void WebGLVertexArrayObjectBase::SetArrayBufferForAttrib(GLuint index,
WebGLBuffer* buffer) {
if (buffer)
buffer->OnAttached();
if (array_buffer_list_[index])
array_buffer_list_[index]->OnDetached(Context()->ContextGL());
array_buffer_list_[index] = buffer;
UpdateAttribBufferBoundStatus();
}
void WebGLVertexArrayObjectBase::SetAttribEnabled(GLuint index, bool enabled) {
DCHECK(index < Context()->MaxVertexAttribs());
attrib_enabled_[index] = enabled;
UpdateAttribBufferBoundStatus();
}
bool WebGLVertexArrayObjectBase::GetAttribEnabled(GLuint index) const {
DCHECK(index < Context()->MaxVertexAttribs());
return attrib_enabled_[index];
}
void WebGLVertexArrayObjectBase::UpdateAttribBufferBoundStatus() {
is_all_enabled_attrib_buffer_bound_ = true;
for (wtf_size_t i = 0; i < attrib_enabled_.size(); ++i) {
if (attrib_enabled_[i] && !array_buffer_list_[i]) {
is_all_enabled_attrib_buffer_bound_ = false;
return;
}
}
}
void WebGLVertexArrayObjectBase::UnbindBuffer(WebGLBuffer* buffer) {
if (bound_element_array_buffer_ == buffer) {
bound_element_array_buffer_->OnDetached(Context()->ContextGL());
bound_element_array_buffer_ = nullptr;
}
for (wtf_size_t i = 0; i < array_buffer_list_.size(); ++i) {
if (array_buffer_list_[i] == buffer) {
array_buffer_list_[i]->OnDetached(Context()->ContextGL());
array_buffer_list_[i] = nullptr;
}
}
UpdateAttribBufferBoundStatus();
}
void WebGLVertexArrayObjectBase::Trace(blink::Visitor* visitor) {
visitor->Trace(bound_element_array_buffer_);
visitor->Trace(array_buffer_list_);
WebGLContextObject::Trace(visitor);
}
} // namespace blink