Gamp v0.0.7-67-g7798ac4
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> GLArrayDataSRef;
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 GLArrayDataSRef 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_view 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 * @param newName persistent std::string_view name of uniform, must be valid through the lifecycle of this instance
100 * @see setLocation(int)
101 * @see setLocation(GL2ES2, int)
102 */
103 void setName(std::string_view newName) noexcept {
104 m_location = -1;
105 m_name = newName;
106 }
107
108 /**
109 * Returns the shader attribute location for this name,
110 * -1 if not yet determined
111 */
112 constexpr GLint location() const noexcept { return m_location; }
113
114 /// Returns true is location() is >= 0, otherwise false
115 constexpr bool hasLocation() const noexcept { return 0<=m_location; }
116
117 /**
118 * Sets the given location of the shader attribute
119 *
120 * @see com.jogamp.opengl.util.glsl.ShaderState#vertexAttribPointer(GL2ES2, GLArrayData)
121 */
122 void setLocation(GLint loc) noexcept { m_location = loc; }
123
124 /**
125 * Retrieves the location of the shader attribute from the linked shader program.
126 * <p>
127 * No validation is performed within the implementation.
128 * </p>
129 * @param gl
130 * @param program
131 * @return &ge;0 denotes a valid attribute location as found and used in the given shader program.
132 * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
133 */
134 bool resolveLocation(const GL&, GLuint program) noexcept {
135 m_location = ::glGetAttribLocation(program, std::string(m_name).c_str());
136 return 0<=m_location;
137 }
138
139 /**
140 * Binds the location of the shader attribute to the given location for the unlinked shader program.
141 * <p>
142 * No validation is performed within the implementation.
143 * </p>
144 * @param gl
145 * @param program
146 * @return the given location
147 */
148 void setLocation(const GL&, GLuint program, GLint loc) noexcept {
149 m_location = loc;
150 ::glBindAttribLocation(program, loc, std::string(m_name).c_str());
151 }
152
153
154 /**
155 * Binds the location of the shader attribute to the given location for the unlinked shader program.
156 * <p>
157 * No validation is performed within the implementation.
158 * </p>
159 * @param gl
160 * @param program
161 */
162 void bindLocation(const GL&, GLuint program, GLint location) noexcept {
163 if( 0 <= location ) {
165 ::glBindAttribLocation(program, location, std::string(m_name).c_str());
166 }
167 }
168
169 /**
170 * Determines whether the data is server side (VBO) and enabled,
171 * or a client side array (false).
172 */
173 constexpr bool isVBO() const noexcept { return m_vboEnabled; }
174
175 /**
176 * The VBO buffer offset if isVBO()
177 */
178 constexpr uintptr_t vboOffset() const noexcept { return m_vboEnabled?m_vboOffset:0; }
179
180 /**
181 * The VBO name or 0 if not a VBO
182 */
183 constexpr GLuint vboName() const noexcept { return m_vboEnabled?m_vboName:0; }
184
185 /**
186 * The VBO usage or 0 if not a VBO
187 * @return 0 if not a GPU buffer, otherwise {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
188 */
189 constexpr GLenum vboUsage() const noexcept { return m_vboEnabled?m_vboUsage:0; }
190
191 /**
192 * The VBO target or 0 if not a VBO
193 * @return 0 if not a GPU buffer, otherwise {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
194 */
195 constexpr GLenum vboTarget() const noexcept { return m_vboEnabled?m_vboTarget:0; }
196
197 /**
198 * Enable or disable use of VBO.
199 * Only possible if a VBO buffer name is defined.
200 * @see #setVBOName(int)
201 */
202 virtual void setVBOEnabled(bool vboEnabled) {
203 m_vboEnabled = vboEnabled;
204 }
205
206 /**
207 * Set the VBO buffer name, if valid (!= 0) enable use of VBO,
208 * otherwise (==0) disable VBO usage.
209 *
210 * @see #setVBOEnabled(boolean)
211 */
212 void setVBOName(GLuint vboName) noexcept {
215 }
216
217 /**
218 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
219 */
220 void setVBOUsage(GLenum vboUsage) noexcept {
222 }
223
224 /**
225 * @param vboTarget either {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
226 */
227 void setVBOTarget(GLenum vboTarget) noexcept {
229 }
230
231 /** The number of components per element */
232 constexpr GLsizei compsPerElem() const noexcept { return m_compsPerElement; }
233
234 /** The component's GL data type, e.g. GL_FLOAT */
235 constexpr GLenum compType() const noexcept { return m_compType; }
236
237 /** The component's static compile-time-type-info (CTTI) jau::type_info, e.g. jau::float_ctti::f32(). */
238 constexpr const jau::type_info& compTypeSignature() const noexcept { return m_compTypeSignature; }
239
240 /** The component's size in bytes */
241 constexpr GLsizei bytesPerComp() const noexcept { return m_bytesPerComp; }
242
243 /**
244 * Returns true if data has been {@link com.jogamp.opengl.util.GLArrayDataEditable#seal(boolean) sealed} (flipped to read), otherwise false (writing mode).
245
246 * @see com.jogamp.opengl.util.GLArrayDataEditable#seal(boolean)
247 * @see com.jogamp.opengl.util.GLArrayDataEditable#seal(GL, boolean)
248 */
249 constexpr bool sealed() const noexcept { return m_sealed; }
250
251 /**
252 * True, if GL shall normalize fixed point data while converting
253 * them into float.
254 * <p>
255 * Default behavior (of the fixed function pipeline) is <code>true</code>
256 * for fixed point data type and <code>false</code> for floating point data types.
257 * </p>
258 */
259 constexpr bool normalized() const noexcept { return m_normalized; }
260
261 /**
262 * @return the byte offset between consecutive components
263 */
264 GLsizei stride() const noexcept { return m_strideB; }
265
266 /** Returns class name of implementing class. */
267 virtual std::string_view className() const noexcept { return "GLArrayData"; }
268
269 /** Returns type signature of implementing class. See compTypeSignature() as well. */
270 virtual const jau::type_info& classSignature() const noexcept = 0;
271
272 /** The data pointer, may be null if using a memory-mapped GPU buffer */
273 virtual const void* data() const noexcept = 0;
274
275 /**
276 * Returns the element position (written elements) if not {@link #sealed()} or
277 * the element limit (available to read) after {@link #sealed()} (flip).
278 * <p>
279 * On element consist out of {@link #getCompsPerElem()} components.
280 * </p>
281 * @see sealed()
282 * @see getByteCount()
283 * @see elemPosition()
284 * @see remainingElems()
285 * @see getElemCapacity()
286 */
287 virtual GLsizei elemCount() const noexcept = 0;
288
289 /**
290 * Returns the byte position (written elements) if not {@link #sealed()} or
291 * the byte limit (available to read) after {@link #sealed()} (flip).
292 * @see sealed()
293 * @see getElemCount()
294 * @see bytePosition()
295 * @see remainingBytes()
296 * @see getByteCapacity()
297 */
298 virtual glmemsize_t byteCount() const noexcept = 0;
299
300 /**
301 * Return the capacity in bytes.
302 * @see getElemCapacity
303 * @see getByteCount
304 * @see bytePosition
305 * @see remainingBytes
306 */
307 virtual glmemsize_t byteCapacity() const noexcept = 0;
308
309 /**
310 * Returns a string with detailed buffer element stats, i.e. sealed, count, position, remaining, limit and capacity.
311 */
312 virtual std::string elemStatsToString() const noexcept { return ""; }
313
314 virtual void destroy(GL&) {
315 // m_buffer = nullptr;
316 m_vboName=0;
317 m_vboEnabled=false;
318 m_vboOffset=0;
319 m_alive = false;
320 }
321
322 protected:
323 std::string toStringImpl() const noexcept {
324 std::string r("GLArrayData");
325 r.append("[").append(m_name)
326 .append(", location ").append(std::to_string(m_location))
327 .append(", isVertexAttribute ").append(std::to_string(m_isVertexAttr))
328 .append(", dataType ").append(jau::toHexString(m_compType))
329 .append(", compsPerElem ").append(std::to_string(m_compsPerElement))
330 .append(", stride ").append(std::to_string(m_strideB)).append("b ").append(std::to_string(m_strideL)).append("c")
331 .append(", vboEnabled ").append(std::to_string(m_vboEnabled))
332 .append(", vboName ").append(std::to_string(m_vboName))
333 .append(", vboUsage ").append(jau::toHexString(m_vboUsage))
334 .append(", vboTarget ").append(jau::toHexString(m_vboTarget))
335 .append(", vboOffset ").append(std::to_string(m_vboOffset))
336 .append(", alive ").append(std::to_string(m_alive)).append("]");
337 return r;
338 }
339
340 public:
341 virtual std::string toString() const noexcept { return toStringImpl(); }
342
343 //
344 // OpenGL pass through funcs
345 //
346
347 /** Sends (creates, updates) the data to the bound vboName buffer, see glBindBuffer(). Issues [glBufferData](https://docs.gl/es3/glBufferData) */
348 void glBufferData(const GL&, glmemsize_t size) const noexcept {
349 ::glBufferData(vboTarget(), size, data(), vboUsage());
350 }
351 /** Binds the vboName() buffer to its vboTarget() on the GPU, i.e. issues [glBindBuffer](https://docs.gl/es3/glBindBuffer) */
352 void glBindBuffer(const GL&, bool on) const noexcept {
353 ::glBindBuffer(vboTarget(), on ? vboName() : 0);
354 }
355
356 /**
357 * Associates the vboName() buffer as an vertex attribute on the GPU, or sends the data if !isVBO().
358 *
359 * Does nothing, if location() is undefined or no data set.
360 *
361 * Issues [glVertexAttribPointer](https://docs.gl/es3/glVertexAttribPointer)
362 */
363 void glVertexAttribPointer(const GL&) const noexcept {
364 if(compsPerElem()==0 || location()<0) return;
365 if(isVBO()) {
367 normalized(), stride(), reinterpret_cast<void*>(vboOffset())); // NOLINT(performance-no-int-to-ptr)
368 } else {
370 normalized(), stride(), data());
371 }
372 }
373
374 protected:
375 struct Private{ explicit Private() = default; };
376
377 template <typename ChildT>
378 std::shared_ptr<ChildT> shared_from_base() {
379 return std::static_pointer_cast<ChildT>(shared_from_this());
380 }
381
382 public:
383 /**
384 * Private ctor for shared_ptr.
385 * @param name persistent std::string_view name of uniform, must be valid through the lifecycle of this instance
386 */
388 std::string_view name, GLsizei componentsPerElement, GLenum componentType, jau::type_info compTypeSignature,
389 bool normalized, GLsizei stride, GLsizei mappedElementCount,
390 bool isVertexAttribute, GLuint vboName, uintptr_t vboOffset, GLenum vboUsage, GLenum vboTarget)
391 {
392 if( GL_ELEMENT_ARRAY_BUFFER == vboTarget ) {
393 // OK ..
394 m_name = "array_buffer";
395 } else if( (0 == vboUsage && 0 == vboTarget) || GL_ARRAY_BUFFER == vboTarget ) {
396 // Set/Check name .. - Required for GLSL case. Validation and debug-name for FFP.
397 m_name = name;
398 if( m_name.empty() ) {
399 throw RenderException("Missing attribute name:\n\t" + toStringImpl(), E_FILE_LINE);
400 }
401 } else if( 0 < vboTarget ) {
402 throw RenderException("Invalid GPUBuffer target: " + jau::toHexString(vboTarget)
403 + ":\n\t" + toStringImpl(), E_FILE_LINE);
404 }
405
406 // immutable types
407 m_compType = componentType;
410 if( 0 == m_bytesPerComp ) {
411 throw RenderException("Given componentType not supported: " + jau::toHexString(componentType) + ":\n\t" + toStringImpl(), E_FILE_LINE);
412 }
413 if( 0 >= componentsPerElement ) {
414 throw RenderException("Invalid number of components: " + std::to_string(componentsPerElement) + ":\n\t" + toStringImpl(), E_FILE_LINE);
415 }
416 m_compsPerElement = componentsPerElement;
417
418 if( 0 < stride && stride < componentsPerElement * m_bytesPerComp ) {
419 throw RenderException("stride (" + std::to_string(stride) + ") lower than component bytes, " + std::to_string(componentsPerElement)
420 + " * " + std::to_string(m_bytesPerComp) + ":\n\t" + toStringImpl(), E_FILE_LINE);
421 }
422 if( 0 < stride && stride % m_bytesPerComp != 0 ) {
423 throw RenderException("stride (" + std::to_string(stride) + ") not a multiple of bpc "
424 + std::to_string(m_bytesPerComp) + ":\n\t" + toStringImpl(), E_FILE_LINE);
425 }
426 m_strideB = (0 == stride) ? componentsPerElement * m_bytesPerComp : stride;
428
429 if( GLBuffers::isGLTypeFixedPoint(componentType) ) {
431 } else {
432 m_normalized = false;
433 }
434 m_mappedElemCount = mappedElementCount;
436
437 // mutable types
438 m_location = -1;
439 // m_buffer = data;
442 m_vboEnabled = 0 != vboName;
443
444 switch( vboUsage ) {
445 case 0: // nop
446 case GL_STATIC_DRAW: // GL
447 case GL_DYNAMIC_DRAW: // GL
448 case GL_STREAM_DRAW: // GL2ES2
449 break;
450 default:
451 throw RenderException("invalid gpuBufferUsage: " + jau::toHexString(vboUsage) + ":\n\t" + toStringImpl(), E_FILE_LINE);
452 }
453 switch( vboTarget ) {
454 case 0: // nop
455 case GL_ARRAY_BUFFER: // GL
456 case GL_ELEMENT_ARRAY_BUFFER: // GL
457 break;
458 default:
459 throw RenderException("invalid gpuBufferTarget: " + jau::toHexString(vboTarget) + ":\n\t" + toStringImpl(), E_FILE_LINE);
460 }
463 m_alive = true;
464 m_sealed = true;
465 }
466
467 protected:
468 // immutable
471 // Class<?> compClazz;
474 /** stride in bytes; strideB >= compsPerElement * bytesPerComp */
475 GLsizei m_strideB;
476 /** stride in logical components */
477 GLsizei m_strideL;
481
482 // mutable
485 // buffer_ref m_buffer;
486 std::string_view m_name;
487 GLuint m_vboName;
488 uintptr_t m_vboOffset;
493
494 };
495
496 inline std::ostream& operator<<(std::ostream& out, const GLArrayData& v) {
497 return out << v.toString();
498 }
499
500 /**@}*/
501
502} // namespace gamp::render::gl
503
504#endif /* GAMP_GLARRAYDATA_HPP_ */
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
constexpr bool hasLocation() const noexcept
Returns true is location() is >= 0, otherwise false.
virtual std::string toString() const noexcept
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.
void setLocation(const GL &, GLuint program, GLint loc) noexcept
Binds the location of the shader attribute to the given location for the unlinked shader program.
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 !...
constexpr GLuint vboName() const noexcept
The VBO name or 0 if not a VBO.
virtual ~GLArrayData() noexcept=default
const GLArrayDataSRef shared()
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.
void setName(std::string_view newName) noexcept
Set a new name for this array.
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
GLArrayData(Private, std::string_view 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.
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.
virtual std::string_view className() const noexcept
Returns class name of implementing class.
constexpr const std::string_view name() const noexcept
The name of the reflecting shader array attribute.
bool resolveLocation(const GL &, GLuint program) noexcept
Retrieves the location of the shader attribute from the linked 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)
#define E_FILE_LINE
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 > GLArrayDataSRef
static constexpr bool isGLTypeFixedPoint(GLenum glType)
Definition GLBuffers.hpp:61
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.
STL namespace.