1// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "openglvertexarrayobject_p.h"
5#include <submissioncontext_p.h>
6#include <renderer_p.h>
7#include <glresourcemanagers_p.h>
8#include <Qt3DRender/private/managers_p.h>
9
10QT_BEGIN_NAMESPACE
11
12namespace Qt3DRender {
13namespace Render {
14namespace OpenGL {
15
16OpenGLVertexArrayObject::OpenGLVertexArrayObject()
17 : m_ctx(nullptr)
18 , m_specified(false)
19 , m_supportsVao(false)
20{}
21
22void OpenGLVertexArrayObject::bind()
23{
24 Q_ASSERT(m_ctx);
25 if (m_supportsVao) {
26 Q_ASSERT(!m_vao.isNull());
27 Q_ASSERT(m_vao->isCreated());
28 m_vao->bind();
29 } else {
30 // Unbind any other VAO that may have been bound and not released correctly
31 if (m_ctx->m_currentVAO != nullptr && m_ctx->m_currentVAO != this)
32 m_ctx->m_currentVAO->release();
33
34 m_ctx->m_currentVAO = this;
35 // We need to specify array and vertex attributes
36 for (const SubmissionContext::VAOVertexAttribute &attr : m_vertexAttributes)
37 m_ctx->enableAttribute(attr);
38 if (!m_indexAttribute.isNull())
39 m_ctx->bindGLBuffer(buffer: m_ctx->m_renderer->glResourceManagers()->glBufferManager()->data(handle: m_indexAttribute),
40 type: GLBuffer::IndexBuffer);
41 }
42}
43
44void OpenGLVertexArrayObject::release()
45{
46 Q_ASSERT(m_ctx);
47 if (m_supportsVao) {
48 Q_ASSERT(!m_vao.isNull());
49 Q_ASSERT(m_vao->isCreated());
50 m_vao->release();
51 } else {
52 if (m_ctx->m_currentVAO == this) {
53 for (const SubmissionContext::VAOVertexAttribute &attr : m_vertexAttributes)
54 m_ctx->disableAttribute(attr);
55 m_ctx->m_currentVAO = nullptr;
56 }
57 }
58}
59
60// called from Render thread
61void OpenGLVertexArrayObject::create(SubmissionContext *ctx, const VAOIdentifier &key)
62{
63 QMutexLocker lock(&m_mutex);
64
65 Q_ASSERT(!m_ctx && !m_vao);
66
67 m_ctx = ctx;
68 m_supportsVao = m_ctx->supportsVAO();
69 if (m_supportsVao) {
70 m_vao.reset(other: new QOpenGLVertexArrayObject());
71 m_vao->create();
72 }
73 m_owners = key;
74}
75
76VAOIdentifier OpenGLVertexArrayObject::key() const
77{
78 return m_owners;
79}
80
81// called from Render thread
82void OpenGLVertexArrayObject::destroy()
83{
84 QMutexLocker locker(&m_mutex);
85
86 Q_ASSERT(m_ctx);
87 cleanup();
88}
89
90void OpenGLVertexArrayObject::cleanup()
91{
92 m_vao.reset();
93 m_ctx = nullptr;
94 m_specified = false;
95 m_supportsVao = false;
96 m_indexAttribute = SubmissionContext::VAOIndexAttribute();
97 m_vertexAttributes.clear();
98}
99
100// called from job
101bool OpenGLVertexArrayObject::isAbandoned(GeometryManager *geomMgr, GLShaderManager *shaderMgr)
102{
103 QMutexLocker lock(&m_mutex);
104
105 if (!m_ctx)
106 return false;
107
108 const bool geometryExists = (geomMgr->data(handle: m_owners.first) != nullptr);
109 const bool shaderExists = (shaderMgr->lookupResource(shaderId: m_owners.second) != nullptr);
110
111 return !geometryExists || !shaderExists;
112}
113
114void OpenGLVertexArrayObject::saveVertexAttribute(const SubmissionContext::VAOVertexAttribute &attr)
115{
116 // Remove any vertexAttribute already at location
117 m_vertexAttributes.erase(first: std::remove_if(first: m_vertexAttributes.begin(),
118 last: m_vertexAttributes.end(),
119 pred: [attr](const SubmissionContext::VAOVertexAttribute &a) {
120 return a.location == attr.location;
121 }),
122 last: m_vertexAttributes.end());
123 m_vertexAttributes.push_back(x: attr);
124}
125
126
127} // namespace OpenGL
128} // namespace Render
129} // namespace Qt3DRender
130
131QT_END_NAMESPACE
132

source code of qt3d/src/plugins/renderers/opengl/renderer/openglvertexarrayobject.cpp