1// Copyright (C) 2014 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 "glbuffer_p.h"
5#include <graphicscontext_p.h>
6
7#if !defined(GL_UNIFORM_BUFFER)
8#define GL_UNIFORM_BUFFER 0x8A11
9#endif
10#if !defined(GL_ARRAY_BUFFER)
11#define GL_ARRAY_BUFFER 0x8892
12#endif
13#if !defined(GL_ELEMENT_ARRAY_BUFFER)
14#define GL_ELEMENT_ARRAY_BUFFER 0x8893
15#endif
16#if !defined(GL_SHADER_STORAGE_BUFFER)
17#define GL_SHADER_STORAGE_BUFFER 0x90D2
18#endif
19#if !defined(GL_PIXEL_PACK_BUFFER)
20#define GL_PIXEL_PACK_BUFFER 0x88EB
21#endif
22#if !defined(GL_PIXEL_UNPACK_BUFFER)
23#define GL_PIXEL_UNPACK_BUFFER 0x88EC
24#endif
25#if !defined(GL_DRAW_INDIRECT_BUFFER)
26#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
27#endif
28
29QT_BEGIN_NAMESPACE
30
31namespace Qt3DRender {
32
33namespace Render {
34
35namespace OpenGL {
36
37// A UBO is created for each ShaderData Shader Pair
38// That means a UBO is unique to a shader/shaderdata
39
40namespace {
41
42GLenum glBufferTypes[] = {
43 GL_ARRAY_BUFFER,
44 GL_UNIFORM_BUFFER,
45 GL_ELEMENT_ARRAY_BUFFER,
46 GL_SHADER_STORAGE_BUFFER,
47 GL_PIXEL_PACK_BUFFER,
48 GL_PIXEL_UNPACK_BUFFER,
49 GL_DRAW_INDIRECT_BUFFER
50};
51
52} // anonymous
53
54GLBuffer::GLBuffer()
55 : m_bufferId(0)
56 , m_isCreated(false)
57 , m_bound(false)
58 , m_lastTarget(GL_ARRAY_BUFFER)
59{
60}
61
62bool GLBuffer::bind(GraphicsContext *ctx, Type t)
63{
64 if (m_bufferId == 0)
65 return false;
66 m_lastTarget = glBufferTypes[t];
67 ctx->openGLContext()->functions()->glBindBuffer(target: m_lastTarget, buffer: m_bufferId);
68 m_bound = true;
69 return true;
70}
71
72bool GLBuffer::release(GraphicsContext *ctx)
73{
74 m_bound = false;
75 ctx->openGLContext()->functions()->glBindBuffer(target: m_lastTarget, buffer: 0);
76 return true;
77}
78
79bool GLBuffer::create(GraphicsContext *ctx)
80{
81 ctx->openGLContext()->functions()->glGenBuffers(n: 1, buffers: &m_bufferId);
82 m_isCreated = true;
83 return m_bufferId != 0;
84}
85
86void GLBuffer::destroy(GraphicsContext *ctx)
87{
88 ctx->openGLContext()->functions()->glDeleteBuffers(n: 1, buffers: &m_bufferId);
89 m_isCreated = false;
90}
91
92void GLBuffer::allocate(GraphicsContext *ctx, uint size, bool dynamic)
93{
94 // Either GL_STATIC_DRAW OR GL_DYNAMIC_DRAW depending on the use case
95 // TO DO: find a way to know how a buffer/QShaderData will be used to use the right usage
96 ctx->openGLContext()->functions()->glBufferData(target: m_lastTarget, size, NULL, usage: dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
97}
98
99void GLBuffer::allocate(GraphicsContext *ctx, const void *data, uint size, bool dynamic)
100{
101 ctx->openGLContext()->functions()->glBufferData(target: m_lastTarget, size, data, usage: dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
102}
103
104void GLBuffer::update(GraphicsContext *ctx, const void *data, uint size, int offset)
105{
106 ctx->openGLContext()->functions()->glBufferSubData(target: m_lastTarget, offset, size, data);
107}
108
109QByteArray GLBuffer::download(GraphicsContext *ctx, uint size)
110{
111 char *gpu_ptr = ctx->mapBuffer(target: m_lastTarget, size);
112 QByteArray data;
113 if (gpu_ptr != nullptr) {
114 data.resize(size);
115 std::copy(first: gpu_ptr, last: gpu_ptr+size, result: data.data());
116 }
117 ctx->unmapBuffer(target: m_lastTarget);
118 return data;
119}
120
121void GLBuffer::bindBufferBase(GraphicsContext *ctx, int bindingPoint, GLBuffer::Type t)
122{
123 ctx->bindBufferBase(target: glBufferTypes[t], bindingIndex: bindingPoint, buffer: m_bufferId);
124}
125
126void GLBuffer::bindBufferBase(GraphicsContext *ctx, int bindingPoint)
127{
128 ctx->bindBufferBase(target: m_lastTarget, bindingIndex: bindingPoint, buffer: m_bufferId);
129}
130
131} // namespace OpenGL
132
133} // namespace Render
134
135} // namespace Qt3DRender
136
137QT_END_NAMESPACE
138

source code of qt3d/src/plugins/renderers/opengl/io/glbuffer.cpp