Gamp v0.0.7-36-g24b1eb6
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
GLArrayData.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11
12#ifndef GAMP_GLARRAYDATA_HPP_
13#define GAMP_GLARRAYDATA_HPP_
14
15#include <memory>
16
19#include <string_view>
20#include <jau/backtrace.hpp>
21#include <jau/type_info.hpp>
22
24 class ShaderState; // fwd
25}
26
28
29 using namespace gamp::render::gl;
30 using namespace gamp::render::gl::glsl;
31
32 /** @defgroup Gamp_GLData Gamp GL Data Managment
33 * OpenGL rendering data management.
34 *
35 * @{
36 */
37
38 class GLArrayData;
39 typedef std::shared_ptr<GLArrayData> GLArrayDataRef;
40
41 /**
42 * Interface for a generic data buffer to be used for OpenGL arrays.
43 */
44 class GLArrayData : public std::enable_shared_from_this<GLArrayData> {
45 public:
46 virtual ~GLArrayData() noexcept = default;
47
48 const GLArrayDataRef shared() { return shared_from_this(); }
49
50 /**
51 * Implementation and type dependent object association.
52 * <p>
53 * One currently known use case is to associate a {@link com.jogamp.opengl.util.glsl.ShaderState ShaderState}
54 * to an GLSL aware vertex attribute object, allowing to use the ShaderState to handle it's
55 * data persistence, location and state change.<br/>
56 * This is implicitly done via {@link com.jogamp.opengl.util.glsl.ShaderState#ownAttribute(GLArrayData, boolean) shaderState.ownAttribute(GLArrayData, boolean)}.
57 * </p>
58 * @param obj implementation and type dependent association
59 * @param enable pass true to enable the association and false to disable it.
60 */
61 virtual void associate(ShaderState& /*st*/, bool /*enable*/) {
62 // nop
63 }
64
65 /**
66 * Validates this instance's parameter. Called automatically by {@link GLArrayDataClient} and {@link GLArrayDataServer}.
67 * {@link GLArrayDataWrapper} does not validate it's instance by itself.
68 *
69 * @param glp the GLProfile to use
70 * @throws GLException if this instance has invalid parameter
71 */
72 virtual void validate(const GL& gl) const {
73 if( !m_alive ) {
74 throw RenderException("Instance !alive " + toString(), E_FILE_LINE);
75 }
76 if( isVertexAttribute() && !gl.glProfile().hasGLSL() ) {
77 throw RenderException("GLSL not supported on " + gl.toString() + ", " + toString(), E_FILE_LINE);
78 }
79 // Skip GLProfile based index, comps, type validation, might not be future proof.
80 // glp.isValidArrayDataType(getIndex(), getCompsPerElem(), getCompType(), isVertexAttribute(), throwException);
81 }
82
83 /**
84 * Returns true if this data set is intended for a GLSL vertex shader attribute,
85 * otherwise false, ie intended for fixed function vertex pointer
86 */
87 constexpr bool isVertexAttribute() const noexcept { return m_isVertexAttr; }
88
89 /**
90 * The name of the reflecting shader array attribute.
91 */
92 constexpr const std::string& name() const noexcept { return m_name; }
93
94 /**
95 * Set a new name for this array.
96 * <p>
97 * This clears the location, i.e. sets it to -1.
98 * </p>
99 * @see setLocation(int)
100 * @see setLocation(GL2ES2, int)
101 */
102 void setName(const std::string& newName) noexcept {
103 m_location = -1;
104 m_name = newName;
105 }
106
107 /**
108 * Returns the shader attribute location for this name,
109 * -1 if not yet determined
110 */
111 constexpr GLint location() const noexcept { return m_location; }
112
113 /**
114 * Sets the given location of the shader attribute
115 *
116 * @see com.jogamp.opengl.util.glsl.ShaderState#vertexAttribPointer(GL2ES2, GLArrayData)
117 */
118 void setLocation(GLint loc) noexcept { m_location = loc; }
119
120 /**
121 * Retrieves the location of the shader attribute from the linked shader program.
122 * <p>
123 * No validation is performed within the implementation.
124 * </p>
125 * @param gl
126 * @param program
127 * @return &ge;0 denotes a valid attribute location as found and used in the given shader program.
128 * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
129 */
130 GLint setLocation(const GL&, GLuint program) noexcept {
131 m_location = glGetAttribLocation(program, m_name.c_str());
132 return m_location;
133 }
134
135 /**
136 * Binds the location of the shader attribute to the given location for the unlinked shader program.
137 * <p>
138 * No validation is performed within the implementation.
139 * </p>
140 * @param gl
141 * @param program
142 * @return the given location
143 */
144 GLint setLocation(const GL&, GLuint program, GLint loc) noexcept {
145 m_location = loc;
146 glBindAttribLocation(program, loc, m_name.c_str());
147 return loc;
148 }
149
150
151 /**
152 * Retrieves the location of the shader attribute from the linked shader program.
153 * <p>
154 * No validation is performed within the implementation.
155 * </p>
156 * @param gl
157 * @param program
158 * @return &ge;0 denotes a valid attribute location as found and used in the given shader program.
159 * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
160 */
161 GLint retrieveLocation(const GL&, GLuint program) noexcept {
162 m_location = glGetAttribLocation(program, m_name.c_str());
163 return m_location;
164 }
165
166 /**
167 * Binds the location of the shader attribute to the given location for the unlinked shader program.
168 * <p>
169 * No validation is performed within the implementation.
170 * </p>
171 * @param gl
172 * @param program
173 */
174 void bindLocation(const GL&, GLuint program, GLint location) noexcept {
175 if( 0 <= location ) {
177 glBindAttribLocation(program, location, m_name.c_str());
178 }
179 }
180
181 /**
182 * Determines whether the data is server side (VBO) and enabled,
183 * or a client side array (false).
184 */
185 constexpr bool isVBO() const noexcept { return m_vboEnabled; }
186
187 /**
188 * The VBO buffer offset if isVBO()
189 */
190 constexpr uintptr_t vboOffset() const noexcept { return m_vboEnabled?m_vboOffset:0; }
191
192 /**
193 * The VBO name or 0 if not a VBO
194 */
195 constexpr GLuint vboName() const noexcept { return m_vboEnabled?m_vboName:0; }
196
197 /**
198 * The VBO usage or 0 if not a VBO
199 * @return 0 if not a GPU buffer, otherwise {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
200 */
201 constexpr GLenum vboUsage() const noexcept { return m_vboEnabled?m_vboUsage:0; }
202
203 /**
204 * The VBO target or 0 if not a VBO
205 * @return 0 if not a GPU buffer, otherwise {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
206 */
207 constexpr GLenum vboTarget() const noexcept { return m_vboEnabled?m_vboTarget:0; }
208
209 /**
210 * Enable or disable use of VBO.
211 * Only possible if a VBO buffer name is defined.
212 * @see #setVBOName(int)
213 */
214 virtual void setVBOEnabled(bool vboEnabled) {
215 m_vboEnabled = vboEnabled;
216 }
217
218 /**
219 * Set the VBO buffer name, if valid (!= 0) enable use of VBO,
220 * otherwise (==0) disable VBO usage.
221 *
222 * @see #setVBOEnabled(boolean)
223 */
224 void setVBOName(GLuint vboName) noexcept {
227 }
228
229 /**
230 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
231 */
232 void setVBOUsage(GLenum vboUsage) noexcept {
234 }
235
236 /**
237 * @param vboTarget either {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
238 */
239 void setVBOTarget(GLenum vboTarget) noexcept {
241 }
242
243 /** The number of components per element */
244 constexpr GLsizei compsPerElem() const noexcept { return m_compsPerElement; }
245
246 /** The component's GL data type, e.g. GL_FLOAT */
247 constexpr GLenum compType() const noexcept { return m_compType; }
248
249 /** The component's static compile-time-type-info (CTTI) jau::type_info, e.g. jau::float_ctti::f32(). */
250 constexpr const jau::type_info& compTypeSignature() const noexcept { return m_compTypeSignature; }
251
252 /** The component's size in bytes */
253 constexpr GLsizei bytesPerComp() const noexcept { return m_bytesPerComp; }
254
255 /**
256 * Returns true if data has been {@link com.jogamp.opengl.util.GLArrayDataEditable#seal(boolean) sealed} (flipped to read), otherwise false (writing mode).
257
258 * @see com.jogamp.opengl.util.GLArrayDataEditable#seal(boolean)
259 * @see com.jogamp.opengl.util.GLArrayDataEditable#seal(GL, boolean)
260 */
261 constexpr bool sealed() const noexcept { return m_sealed; }
262
263 /**
264 * True, if GL shall normalize fixed point data while converting
265 * them into float.
266 * <p>
267 * Default behavior (of the fixed function pipeline) is <code>true</code>
268 * for fixed point data type and <code>false</code> for floating point data types.
269 * </p>
270 */
271 constexpr bool normalized() const noexcept { return m_normalized; }
272
273 /**
274 * @return the byte offset between consecutive components
275 */
276 GLsizei stride() const noexcept { return m_strideB; }
277
278 /** Returns class name of implementing class. */
279 virtual std::string_view className() const noexcept { return "GLArrayData"; }
280
281 /** Returns type signature of implementing class. See compTypeSignature() as well. */
282 virtual const jau::type_info& classSignature() const noexcept = 0;
283
284 /** The data pointer, may be null if using a memory-mapped GPU buffer */
285 virtual const void* data() const noexcept = 0;
286
287 /**
288 * Returns the element position (written elements) if not {@link #sealed()} or
289 * the element limit (available to read) after {@link #sealed()} (flip).
290 * <p>
291 * On element consist out of {@link #getCompsPerElem()} components.
292 * </p>
293 * @see sealed()
294 * @see getByteCount()
295 * @see elemPosition()
296 * @see remainingElems()
297 * @see getElemCapacity()
298 */
299 virtual GLsizei elemCount() const noexcept = 0;
300
301 /**
302 * Returns the byte position (written elements) if not {@link #sealed()} or
303 * the byte limit (available to read) after {@link #sealed()} (flip).
304 * @see sealed()
305 * @see getElemCount()
306 * @see bytePosition()
307 * @see remainingBytes()
308 * @see getByteCapacity()
309 */
310 virtual glmemsize_t byteCount() const noexcept = 0;
311
312 /**
313 * Return the capacity in bytes.
314 * @see getElemCapacity
315 * @see getByteCount
316 * @see bytePosition
317 * @see remainingBytes
318 */
319 virtual glmemsize_t byteCapacity() const noexcept = 0;
320
321 /**
322 * Returns a string with detailed buffer element stats, i.e. sealed, count, position, remaining, limit and capacity.
323 */
324 virtual std::string elemStatsToString() const noexcept { return ""; }
325
326 virtual void destroy(GL&) {
327 // m_buffer = nullptr;
328 m_vboName=0;
329 m_vboEnabled=false;
330 m_vboOffset=0;
331 m_alive = false;
332 }
333
334 protected:
335 std::string toStringImpl() const noexcept {
336 std::string r("GLArrayData");
337 r.append("[").append(m_name)
338 .append(", location ").append(std::to_string(m_location))
339 .append(", isVertexAttribute ").append(std::to_string(m_isVertexAttr))
340 .append(", dataType ").append(jau::to_hexstring(m_compType))
341 .append(", compsPerElem ").append(std::to_string(m_compsPerElement))
342 .append(", stride ").append(std::to_string(m_strideB)).append("b ").append(std::to_string(m_strideL)).append("c")
343 .append(", vboEnabled ").append(std::to_string(m_vboEnabled))
344 .append(", vboName ").append(std::to_string(m_vboName))
345 .append(", vboUsage ").append(jau::to_hexstring(m_vboUsage))
346 .append(", vboTarget ").append(jau::to_hexstring(m_vboTarget))
347 .append(", vboOffset ").append(std::to_string(m_vboOffset))
348 .append(", alive ").append(std::to_string(m_alive)).append("]");
349 return r;
350 }
351
352 public:
353 virtual std::string toString() const noexcept { return toStringImpl(); }
354
355 //
356 // OpenGL pass through funcs
357 //
358
359 /** Sends (creates, updates) the data to the bound vboName buffer, see glBindBuffer(). Issues [glBufferData](https://docs.gl/es3/glBufferData) */
360 void glBufferData(const GL&, glmemsize_t size) const noexcept {
361 ::glBufferData(vboTarget(), size, data(), vboUsage());
362 }
363 /** Binds the vboName() buffer to its vboTarget() on the GPU, i.e. issues [glBindBuffer](https://docs.gl/es3/glBindBuffer) */
364 void glBindBuffer(const GL&, bool on) const noexcept {
365 ::glBindBuffer(vboTarget(), on ? vboName() : 0);
366 }
367
368 /**
369 * Associates the vboName() buffer as an vertex attribute on the GPU, or sends the data if !isVBO().
370 *
371 * Does nothing, if location() is undefined or no data set.
372 *
373 * Issues [glVertexAttribPointer](https://docs.gl/es3/glVertexAttribPointer)
374 */
375 void glVertexAttribPointer(const GL&) const noexcept {
376 if(compsPerElem()==0 || location()<0) return;
377 if(isVBO()) {
379 normalized(), stride(), reinterpret_cast<void*>(vboOffset())); // NOLINT(performance-no-int-to-ptr)
380 } else {
382 normalized(), stride(), data());
383 }
384 }
385
386 protected:
387 struct Private{ explicit Private() = default; };
388
389 template <typename ChildT>
390 std::shared_ptr<ChildT> shared_from_base() {
391 return std::static_pointer_cast<ChildT>(shared_from_this());
392 }
393
394 public:
395 /** Private ctor for shared_ptr. */
397 const std::string& name, GLsizei componentsPerElement, GLenum componentType, jau::type_info compTypeSignature,
398 bool normalized, GLsizei stride, GLsizei mappedElementCount,
399 bool isVertexAttribute, GLuint vboName, uintptr_t vboOffset, GLenum vboUsage, GLenum vboTarget)
400 {
401 if( GL_ELEMENT_ARRAY_BUFFER == vboTarget ) {
402 // OK ..
403 } else if( (0 == vboUsage && 0 == vboTarget) || GL_ARRAY_BUFFER == vboTarget ) {
404 // Set/Check name .. - Required for GLSL case. Validation and debug-name for FFP.
405 m_name = name;
406 if( m_name.empty() ) {
407 throw RenderException("Missing attribute name:\n\t" + toStringImpl(), E_FILE_LINE);
408 }
409 } else if( 0 < vboTarget ) {
410 throw RenderException("Invalid GPUBuffer target: " + jau::to_hexstring(vboTarget)
411 + ":\n\t" + toStringImpl(), E_FILE_LINE);
412 }
413
414 // immutable types
415 m_compType = componentType;
418 if( 0 == m_bytesPerComp ) {
419 throw RenderException("Given componentType not supported: " + jau::to_hexstring(componentType) + ":\n\t" + toStringImpl(), E_FILE_LINE);
420 }
421 if( 0 >= componentsPerElement ) {
422 throw RenderException("Invalid number of components: " + std::to_string(componentsPerElement) + ":\n\t" + toStringImpl(), E_FILE_LINE);
423 }
424 m_compsPerElement = componentsPerElement;
425
426 if( 0 < stride && stride < componentsPerElement * m_bytesPerComp ) {
427 throw RenderException("stride (" + std::to_string(stride) + ") lower than component bytes, " + std::to_string(componentsPerElement)
428 + " * " + std::to_string(m_bytesPerComp) + ":\n\t" + toStringImpl(), E_FILE_LINE);
429 }
430 if( 0 < stride && stride % m_bytesPerComp != 0 ) {
431 throw RenderException("stride (" + std::to_string(stride) + ") not a multiple of bpc "
432 + std::to_string(m_bytesPerComp) + ":\n\t" + toStringImpl(), E_FILE_LINE);
433 }
434 m_strideB = (0 == stride) ? componentsPerElement * m_bytesPerComp : stride;
436
437 if( GLBuffers::isGLTypeFixedPoint(componentType) ) {
439 } else {
440 m_normalized = false;
441 }
442 m_mappedElemCount = mappedElementCount;
444
445 // mutable types
446 m_location = -1;
447 // m_buffer = data;
450 m_vboEnabled = 0 != vboName;
451
452 switch( vboUsage ) {
453 case 0: // nop
454 case GL_STATIC_DRAW: // GL
455 case GL_DYNAMIC_DRAW: // GL
456 case GL_STREAM_DRAW: // GL2ES2
457 break;
458 default:
459 throw RenderException("invalid gpuBufferUsage: " + jau::to_hexstring(vboUsage) + ":\n\t" + toStringImpl(), E_FILE_LINE);
460 }
461 switch( vboTarget ) {
462 case 0: // nop
463 case GL_ARRAY_BUFFER: // GL
464 case GL_ELEMENT_ARRAY_BUFFER: // GL
465 break;
466 default:
467 throw RenderException("invalid gpuBufferTarget: " + jau::to_hexstring(vboTarget) + ":\n\t" + toStringImpl(), E_FILE_LINE);
468 }
471 m_alive = true;
472 m_sealed = true;
473 }
474
475 protected:
476 // immutable
479 // Class<?> compClazz;
482 /** stride in bytes; strideB >= compsPerElement * bytesPerComp */
483 GLsizei m_strideB;
484 /** stride in logical components */
485 GLsizei m_strideL;
489
490 // mutable
493 // buffer_ref m_buffer;
494 std::string m_name;
495 GLuint m_vboName;
496 uintptr_t m_vboOffset;
501
502 };
503
504 inline std::ostream& operator<<(std::ostream& out, const GLArrayData& v) {
505 return out << v.toString();
506 }
507
508 /**@}*/
509
510} // namespace gamp::render::gl
511
512#endif /* GAMP_GLARRAYDATA_HPP_ */
#define E_FILE_LINE
Interface for a generic data buffer to be used for OpenGL arrays.
constexpr bool sealed() const noexcept
Returns true if data has been sealed (flipped to read), otherwise false (writing mode).
virtual void validate(const GL &gl) const
Validates this instance's parameter.
void setVBOTarget(GLenum vboTarget) noexcept
virtual std::string toString() const noexcept
GLint setLocation(const GL &, GLuint program) noexcept
Retrieves the location of the shader attribute from the linked shader program.
virtual GLsizei elemCount() const noexcept=0
Returns the element position (written elements) if not sealed() or the element limit (available to re...
virtual const void * data() const noexcept=0
The data pointer, may be null if using a memory-mapped GPU buffer.
void glBufferData(const GL &, glmemsize_t size) const noexcept
Sends (creates, updates) the data to the bound vboName buffer, see glBindBuffer().
constexpr uintptr_t vboOffset() const noexcept
The VBO buffer offset if isVBO()
void bindLocation(const GL &, GLuint program, GLint location) noexcept
Binds the location of the shader attribute to the given location for the unlinked shader program.
constexpr const std::string & name() const noexcept
The name of the reflecting shader array attribute.
void setVBOName(GLuint vboName) noexcept
Set the VBO buffer name, if valid (!= 0) enable use of VBO, otherwise (==0) disable VBO usage.
virtual void associate(ShaderState &, bool)
Implementation and type dependent object association.
virtual std::string elemStatsToString() const noexcept
Returns a string with detailed buffer element stats, i.e.
constexpr GLsizei compsPerElem() const noexcept
The number of components per element.
virtual glmemsize_t byteCapacity() const noexcept=0
Return the capacity in bytes.
constexpr const jau::type_info & compTypeSignature() const noexcept
The component's static compile-time-type-info (CTTI) jau::type_info, e.g.
virtual void setVBOEnabled(bool vboEnabled)
Enable or disable use of VBO.
void glBindBuffer(const GL &, bool on) const noexcept
Binds the vboName() buffer to its vboTarget() on the GPU, i.e.
void glVertexAttribPointer(const GL &) const noexcept
Associates the vboName() buffer as an vertex attribute on the GPU, or sends the data if !...
void setName(const std::string &newName) noexcept
Set a new name for this array.
constexpr GLuint vboName() const noexcept
The VBO name or 0 if not a VBO.
virtual ~GLArrayData() noexcept=default
constexpr bool isVertexAttribute() const noexcept
Returns true if this data set is intended for a GLSL vertex shader attribute, otherwise false,...
GLsizei m_strideB
stride in bytes; strideB >= compsPerElement * bytesPerComp
constexpr GLenum vboUsage() const noexcept
The VBO usage or 0 if not a VBO.
GLArrayData(Private, const std::string &name, GLsizei componentsPerElement, GLenum componentType, jau::type_info compTypeSignature, bool normalized, GLsizei stride, GLsizei mappedElementCount, bool isVertexAttribute, GLuint vboName, uintptr_t vboOffset, GLenum vboUsage, GLenum vboTarget)
Private ctor for shared_ptr.
std::string toStringImpl() const noexcept
GLsizei stride() const noexcept
constexpr GLsizei bytesPerComp() const noexcept
The component's size in bytes.
constexpr bool normalized() const noexcept
True, if GL shall normalize fixed point data while converting them into float.
GLsizei m_strideL
stride in logical components
constexpr bool isVBO() const noexcept
Determines whether the data is server side (VBO) and enabled, or a client side array (false).
constexpr GLint location() const noexcept
Returns the shader attribute location for this name, -1 if not yet determined.
std::shared_ptr< ChildT > shared_from_base()
constexpr GLenum vboTarget() const noexcept
The VBO target or 0 if not a VBO.
void setVBOUsage(GLenum vboUsage) noexcept
virtual glmemsize_t byteCount() const noexcept=0
Returns the byte position (written elements) if not sealed() or the byte limit (available to read) af...
virtual const jau::type_info & classSignature() const noexcept=0
Returns type signature of implementing class.
void setLocation(GLint loc) noexcept
Sets the given location of the shader attribute.
constexpr GLenum compType() const noexcept
The component's GL data type, e.g.
GLint retrieveLocation(const GL &, GLuint program) noexcept
Retrieves the location of the shader attribute from the linked shader program.
virtual std::string_view className() const noexcept
Returns class name of implementing class.
GLint setLocation(const GL &, GLuint program, GLint loc) noexcept
Binds the location of the shader attribute to the given location for the unlinked shader program.
ShaderState allows to sharing data between shader programs, while updating the attribute and uniform ...
Generic type information using either Runtime type information (RTTI) or Compile time type informatio...
std::ostream & operator<<(std::ostream &os, const T v)
static constexpr GLsizei sizeOfGLType(GLenum glType)
Definition GLBuffers.hpp:99
GLsizeiptr glmemsize_t
Compatible with ssize_t.
Definition GLBuffers.hpp:26
std::shared_ptr< GLArrayData > GLArrayDataRef
static constexpr bool isGLTypeFixedPoint(GLenum glType)
Definition GLBuffers.hpp:61
std::string to_hexstring(value_type const &v, const bool skipLeading0x=false) noexcept
Produce a lower-case hexadecimal string representation with leading 0x in MSB of the given pointer.
STL namespace.