1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the demonstration applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#ifndef GLBUFFERS_H
52#define GLBUFFERS_H
53
54//#include <GL/glew.h>
55#include "glextensions.h"
56
57#include <QtWidgets>
58#include <QtOpenGL>
59
60#define BUFFER_OFFSET(i) ((char*)0 + (i))
61#define SIZE_OF_MEMBER(cls, member) sizeof(static_cast<cls *>(nullptr)->member)
62
63#define GLBUFFERS_ASSERT_OPENGL(prefix, assertion, returnStatement) \
64if (m_failed || !(assertion)) { \
65 if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \
66 m_failed = true; \
67 returnStatement; \
68}
69
70void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
71
72QT_BEGIN_NAMESPACE
73class QMatrix4x4;
74QT_END_NAMESPACE
75
76class GLTexture
77{
78public:
79 GLTexture();
80 virtual ~GLTexture();
81 virtual void bind() = 0;
82 virtual void unbind() = 0;
83 virtual bool failed() const {return m_failed;}
84protected:
85 GLuint m_texture = 0;
86 bool m_failed = false;
87};
88
89class GLFrameBufferObject
90{
91public:
92 friend class GLRenderTargetCube;
93 // friend class GLRenderTarget2D;
94
95 GLFrameBufferObject(int width, int height);
96 virtual ~GLFrameBufferObject();
97 bool isComplete();
98 virtual bool failed() const {return m_failed;}
99protected:
100 void setAsRenderTarget(bool state = true);
101 GLuint m_fbo = 0;
102 GLuint m_depthBuffer = 0;
103 int m_width, m_height;
104 bool m_failed = false;
105};
106
107class GLTexture2D : public GLTexture
108{
109public:
110 GLTexture2D(int width, int height);
111 explicit GLTexture2D(const QString &fileName, int width = 0, int height = 0);
112 void load(int width, int height, QRgb *data);
113 void bind() override;
114 void unbind() override;
115};
116
117class GLTexture3D : public GLTexture
118{
119public:
120 GLTexture3D(int width, int height, int depth);
121 // TODO: Implement function below
122 //GLTexture3D(const QString& fileName, int width = 0, int height = 0);
123 void load(int width, int height, int depth, QRgb *data);
124 void bind() override;
125 void unbind() override;
126};
127
128class GLTextureCube : public GLTexture
129{
130public:
131 GLTextureCube(int size);
132 explicit GLTextureCube(const QStringList &fileNames, int size = 0);
133 void load(int size, int face, QRgb *data);
134 void bind() override;
135 void unbind() override;
136};
137
138// TODO: Define and implement class below
139//class GLRenderTarget2D : public GLTexture2D
140
141class GLRenderTargetCube : public GLTextureCube
142{
143public:
144 GLRenderTargetCube(int size);
145 // begin rendering to one of the cube's faces. 0 <= face < 6
146 void begin(int face);
147 // end rendering
148 void end();
149 bool failed() const override { return m_failed || m_fbo.failed(); }
150
151 static void getViewMatrix(QMatrix4x4& mat, int face);
152 static void getProjectionMatrix(QMatrix4x4& mat, float nearZ, float farZ);
153private:
154 GLFrameBufferObject m_fbo;
155};
156
157struct VertexDescription
158{
159 enum
160 {
161 Null = 0, // Terminates a VertexDescription array
162 Position,
163 TexCoord,
164 Normal,
165 Color,
166 };
167 int field; // Position, TexCoord, Normal, Color
168 int type; // GL_FLOAT, GL_UNSIGNED_BYTE
169 int count; // number of elements
170 int offset; // field's offset into vertex struct
171 int index; // 0 (unused at the moment)
172};
173
174// Implementation of interleaved buffers.
175// 'T' is a struct which must include a null-terminated static array
176// 'VertexDescription* description'.
177// Example:
178/*
179struct Vertex
180{
181 GLfloat position[3];
182 GLfloat texCoord[2];
183 GLfloat normal[3];
184 GLbyte color[4];
185 static VertexDescription description[];
186};
187
188VertexDescription Vertex::description[] = {
189 {VertexDescription::Position, GL_FLOAT, SIZE_OF_MEMBER(Vertex, position) / sizeof(GLfloat), offsetof(Vertex, position), 0},
190 {VertexDescription::TexCoord, GL_FLOAT, SIZE_OF_MEMBER(Vertex, texCoord) / sizeof(GLfloat), offsetof(Vertex, texCoord), 0},
191 {VertexDescription::Normal, GL_FLOAT, SIZE_OF_MEMBER(Vertex, normal) / sizeof(GLfloat), offsetof(Vertex, normal), 0},
192 {VertexDescription::Color, GL_BYTE, SIZE_OF_MEMBER(Vertex, color) / sizeof(GLbyte), offsetof(Vertex, color), 0},
193 {VertexDescription::Null, 0, 0, 0, 0},
194};
195*/
196template<class T>
197class GLVertexBuffer
198{
199public:
200 GLVertexBuffer(int length, const T *data = nullptr, int mode = GL_STATIC_DRAW)
201 {
202 GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::GLVertexBuffer", glGenBuffers && glBindBuffer && glBufferData, return)
203
204 glGenBuffers(1, &m_buffer);
205 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
206 glBufferData(GL_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode);
207 }
208
209 ~GLVertexBuffer()
210 {
211 GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::~GLVertexBuffer", glDeleteBuffers, return)
212
213 glDeleteBuffers(1, &m_buffer);
214 }
215
216 void bind()
217 {
218 GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::bind", glBindBuffer, return)
219
220 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
221 for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) {
222 switch (desc->field) {
223 case VertexDescription::Position:
224 glVertexPointer(size: desc->count, type: desc->type, stride: sizeof(T), BUFFER_OFFSET(desc->offset));
225 glEnableClientState(GL_VERTEX_ARRAY);
226 break;
227 case VertexDescription::TexCoord:
228 glTexCoordPointer(size: desc->count, type: desc->type, stride: sizeof(T), BUFFER_OFFSET(desc->offset));
229 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
230 break;
231 case VertexDescription::Normal:
232 glNormalPointer(type: desc->type, stride: sizeof(T), BUFFER_OFFSET(desc->offset));
233 glEnableClientState(GL_NORMAL_ARRAY);
234 break;
235 case VertexDescription::Color:
236 glColorPointer(size: desc->count, type: desc->type, stride: sizeof(T), BUFFER_OFFSET(desc->offset));
237 glEnableClientState(GL_COLOR_ARRAY);
238 break;
239 default:
240 break;
241 }
242 }
243 }
244
245 void unbind()
246 {
247 GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unbind", glBindBuffer, return)
248
249 glBindBuffer(GL_ARRAY_BUFFER, 0);
250 for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) {
251 switch (desc->field) {
252 case VertexDescription::Position:
253 glDisableClientState(GL_VERTEX_ARRAY);
254 break;
255 case VertexDescription::TexCoord:
256 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
257 break;
258 case VertexDescription::Normal:
259 glDisableClientState(GL_NORMAL_ARRAY);
260 break;
261 case VertexDescription::Color:
262 glDisableClientState(GL_COLOR_ARRAY);
263 break;
264 default:
265 break;
266 }
267 }
268 }
269
270 int length() const {return m_length;}
271
272 T *lock()
273 {
274 GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::lock", glBindBuffer && glMapBuffer, return nullptr)
275
276 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
277 //glBufferData(GL_ARRAY_BUFFER, m_length, NULL, m_mode);
278 GLvoid* buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
279 m_failed = (buffer == nullptr);
280 return reinterpret_cast<T *>(buffer);
281 }
282
283 void unlock()
284 {
285 GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unlock", glBindBuffer && glUnmapBuffer, return)
286
287 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
288 glUnmapBuffer(GL_ARRAY_BUFFER);
289 }
290
291 bool failed()
292 {
293 return m_failed;
294 }
295
296private:
297 int m_length = 0;
298 int m_mode = 0;
299 GLuint m_buffer = 0;
300 bool m_failed = false;
301};
302
303template<class T>
304class GLIndexBuffer
305{
306public:
307 GLIndexBuffer(int length, const T *data = nullptr, int mode = GL_STATIC_DRAW)
308 : m_length(0)
309 , m_mode(mode)
310 , m_buffer(0)
311 , m_failed(false)
312 {
313 GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::GLIndexBuffer", glGenBuffers && glBindBuffer && glBufferData, return)
314
315 glGenBuffers(1, &m_buffer);
316 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
317 glBufferData(GL_ELEMENT_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode);
318 }
319
320 ~GLIndexBuffer()
321 {
322 GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::~GLIndexBuffer", glDeleteBuffers, return)
323
324 glDeleteBuffers(1, &m_buffer);
325 }
326
327 void bind()
328 {
329 GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::bind", glBindBuffer, return)
330
331 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
332 }
333
334 void unbind()
335 {
336 GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unbind", glBindBuffer, return)
337
338 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
339 }
340
341 int length() const {return m_length;}
342
343 T *lock()
344 {
345 GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::lock", glBindBuffer && glMapBuffer, return nullptr)
346
347 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
348 GLvoid* buffer = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_WRITE);
349 m_failed = (buffer == nullptr);
350 return reinterpret_cast<T *>(buffer);
351 }
352
353 void unlock()
354 {
355 GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unlock", glBindBuffer && glUnmapBuffer, return)
356
357 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
358 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
359 }
360
361 bool failed()
362 {
363 return m_failed;
364 }
365
366private:
367 int m_length, m_mode;
368 GLuint m_buffer;
369 bool m_failed;
370};
371
372#endif
373

source code of qtbase/examples/widgets/graphicsview/boxes/glbuffers.h