Gamp v0.0.7-36-g24b1eb6
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
GLBuffers.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_GLBUFFERS_HPP_
13#define GAMP_GLBUFFERS_HPP_
14
16
17namespace gamp::render::gl::data {
18 using namespace gamp::render::gl;
19
20 /** \addtogroup Gamp_GLData
21 *
22 * @{
23 */
24
25 /** Compatible with ssize_t */
26 typedef GLsizeiptr glmemsize_t;
27
28 /**
29 * OpenGL buffer related routines.
30 */
31 class GLBuffers {
32 public:
33 /**
34 * @param glType GL primitive type
35 * @return false if one of GL primitive unsigned types, otherwise true
36 * GL_UNSIGNED_BYTE, <br/>
37 * GL_UNSIGNED_SHORT, <br/>
38 * GL_UNSIGNED_INT, <br/>
39 * GL_HILO16_NV <br/>
40 */
41 constexpr static bool isSignedGLType(GLenum glType) {
42 switch (glType) { // 29
43 case GL_UNSIGNED_BYTE:
44 case GL_UNSIGNED_SHORT:
45 case GL_UNSIGNED_INT:
46 case GL_HILO16_NV: // GL2
47 return false;
48 default: return true;
49
50 }
51 }
52
53 /**
54 * @param glType GL primitive type
55 * @return false if one of GL primitive floating point types, otherwise true
56 * GL_FLOAT, <br/>
57 * GL_HALF_FLOAT, <br/>
58 * GL_HALF_FLOAT_OES, <br/>
59 * GL_DOUBLE <br/>
60 */
61 constexpr static bool isGLTypeFixedPoint(GLenum glType) {
62 switch(glType) {
63 case GL_FLOAT:
64 case GL_HALF_FLOAT:
65 // case GL_HALF_FLOAT_OES: // GLES2
66 case GL_DOUBLE: // GL2GL3
67 return false;
68
69 default:
70 return true;
71 }
72 }
73
74 /**
75 * @param glType shall be one of (31) <br/>
76 * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
77 * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
78 * <br/>
79 * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
80 * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
81 * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
82 * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
83 * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
84 * GL.GL_HALF_FLOAT, GLES2.GL_HALF_FLOAT_OES: <br/>
85 * <br/>
86 * GL_FIXED, GL_INT <br/>
87 * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
88 * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
89 * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
90 * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
91 * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
92 * <br/>
93 * GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
94 * <br/>
95 * GL_FLOAT, GL_DOUBLE <br/>
96 *
97 * @return 0 if glType is unhandled, otherwise the actual value > 0
98 */
99 constexpr static GLsizei sizeOfGLType(GLenum glType) {
100 switch (glType) { // 29
101 // case GL2.GL_BITMAP:
102 case GL_BYTE:
103 case GL_UNSIGNED_BYTE:
104 case GL_UNSIGNED_BYTE_3_3_2: // GL2GL3
105 case GL_UNSIGNED_BYTE_2_3_3_REV: // GL2GL3
106 return sizeof(uint8_t);
107
108 case GL_SHORT:
109 case GL_UNSIGNED_SHORT:
110 case GL_UNSIGNED_SHORT_5_6_5:
111 case GL_UNSIGNED_SHORT_5_6_5_REV: // GL2GL3
112 case GL_UNSIGNED_SHORT_4_4_4_4:
113 case GL_UNSIGNED_SHORT_4_4_4_4_REV: // GL2GL3
114 case GL_UNSIGNED_SHORT_5_5_5_1:
115 case GL_UNSIGNED_SHORT_1_5_5_5_REV: // GL2GL3
116 case GL_UNSIGNED_SHORT_8_8_APPLE: // GL2
117 case GL_UNSIGNED_SHORT_8_8_REV_APPLE: // GL2
118 case GL_HALF_FLOAT:
119 // case GL_HALF_FLOAT_OES: // GLES2
120 return sizeof(uint16_t);
121
122 case GL_FIXED:
123 case GL_INT: // GL2ES2
124 case GL_UNSIGNED_INT:
125 case GL_UNSIGNED_INT_8_8_8_8: // GL2GL3
126 case GL_UNSIGNED_INT_8_8_8_8_REV: // GL2GL3
127 case GL_UNSIGNED_INT_10_10_10_2: // GL2ES2
128 case GL_UNSIGNED_INT_2_10_10_10_REV: // GL2ES2
129 case GL_UNSIGNED_INT_24_8:
130 case GL_UNSIGNED_INT_10F_11F_11F_REV:
131 case GL_UNSIGNED_INT_5_9_9_9_REV: // GL2ES3
132 case GL_HILO16_NV: // GL2
133 case GL_SIGNED_HILO16_NV: // GL2
134 return sizeof(uint32_t);
135
136 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: // GL2ES3
137 return sizeof(uint64_t);
138
139 case GL_FLOAT:
140 return sizeof(jau::float32_t);
141
142 case GL_DOUBLE: // GL2GL3
143 return sizeof(jau::float64_t);
144
145 default: return 0;
146 }
147 }
148
149#if 0
150 /**
151 * @param glType shall be one of (31) <br/>
152 * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
153 * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
154 * <br/>
155 * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
156 * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
157 * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
158 * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
159 * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
160 * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
161 * <br/>
162 * GL_FIXED, GL_INT <br/>
163 * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
164 * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
165 * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
166 * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
167 * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
168 * <br/>
169 * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
170 * <br/>
171 * GL_FLOAT, GL_DOUBLE <br/>
172 *
173 * @return null if glType is unhandled, otherwise the new Buffer object
174 */
175 static glbuffer_ref newGLBuffer(GLenum glType, glmemsize_t numElements) {
176 switch (glType) { // 29
177 case GL_BYTE:
178 return jau::DataBuffer<int8_t, glmemsize_t>::create(numElements);
179
180 case GL_UNSIGNED_BYTE:
181 case GL_UNSIGNED_BYTE_3_3_2: // GL2GL3
182 case GL_UNSIGNED_BYTE_2_3_3_REV: // GL2GL3
183 return jau::DataBuffer<uint8_t, glmemsize_t>::create(numElements);
184
185 case GL_SHORT:
186 return jau::DataBuffer<int16_t, glmemsize_t>::create(numElements);
187
188 case GL_UNSIGNED_SHORT:
189 case GL_UNSIGNED_SHORT_5_6_5:
190 case GL_UNSIGNED_SHORT_5_6_5_REV: // GL2GL3
191 case GL_UNSIGNED_SHORT_4_4_4_4:
192 case GL_UNSIGNED_SHORT_4_4_4_4_REV: // GL2GL3
193 case GL_UNSIGNED_SHORT_5_5_5_1:
194 case GL_UNSIGNED_SHORT_1_5_5_5_REV: // GL2GL3
195 case GL_UNSIGNED_SHORT_8_8_APPLE: // GL2
196 case GL_UNSIGNED_SHORT_8_8_REV_APPLE: // GL2
197 case GL_HALF_FLOAT:
198 // case GL_HALF_FLOAT_OES: // GLES2
199 return jau::DataBuffer<uint16_t, glmemsize_t>::create(numElements);
200
201 case GL_INT: // GL2ES2
202 return jau::DataBuffer<int32_t, glmemsize_t>::create(numElements);
203
204 case GL_FIXED:
205 case GL_SIGNED_HILO16_NV: // GL2
206 case GL_UNSIGNED_INT:
207 case GL_UNSIGNED_INT_8_8_8_8: // GL2GL3
208 case GL_UNSIGNED_INT_8_8_8_8_REV: // GL2GL3
209 case GL_UNSIGNED_INT_10_10_10_2: // GL2ES2
210 case GL_UNSIGNED_INT_2_10_10_10_REV: // GL2ES2
211 case GL_UNSIGNED_INT_24_8:
212 case GL_UNSIGNED_INT_10F_11F_11F_REV:
213 case GL_UNSIGNED_INT_5_9_9_9_REV: // GL2GL3
214 case GL_HILO16_NV: // GL2
215 return jau::DataBuffer<uint32_t, glmemsize_t>::create(numElements);
216
217 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: // GL2ES3
218 return jau::DataBuffer<uint64_t, glmemsize_t>::create(numElements);
219
220 case GL_FLOAT:
221 return jau::DataBuffer<jau::float32_t, glmemsize_t>::create(numElements);
222
223 case GL_DOUBLE: // GL2GL3
224 return jau::DataBuffer<jau::float64_t, glmemsize_t>::create(numElements);
225
226 default: return nullptr;
227 }
228 }
229
230 /**
231 * @param glType shall be one of (31) <br/>
232 * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
233 * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
234 * <br/>
235 * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
236 * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
237 * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
238 * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
239 * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
240 * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
241 * <br/>
242 * GL_FIXED, GL_INT <br/>
243 * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
244 * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
245 * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
246 * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
247 * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
248 * <br/>
249 * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
250 * <br/>
251 * GL_FLOAT, GL_DOUBLE <br/>
252 * @return null if glType is unhandled or parent is null or bufLen is 0, otherwise the new Buffer object
253 */
254 static glbuffer_ref sliceGLBuffer(const glbuffer_ref& parent, glmemsize_t pos, glmemsize_t length, GLenum glType) {
255 if (!parent || length == 0) {
256 return nullptr;
257 }
258 switch (glType) { // 29
259 case GL_BYTE:
260 case GL_UNSIGNED_BYTE:
261 case GL_UNSIGNED_BYTE_3_3_2: // GL2GL3
262 case GL_UNSIGNED_BYTE_2_3_3_REV: // GL2GL3
263 return parent->slice(pos, length); // slice and duplicate
264
265 case GL_SHORT:
266 case GL_UNSIGNED_SHORT:
267 case GL_UNSIGNED_SHORT_5_6_5:
268 case GL_UNSIGNED_SHORT_5_6_5_REV: // GL2GL3
269 case GL_UNSIGNED_SHORT_4_4_4_4:
270 case GL_UNSIGNED_SHORT_4_4_4_4_REV: // GL2GL3
271 case GL_UNSIGNED_SHORT_5_5_5_1:
272 case GL_UNSIGNED_SHORT_1_5_5_5_REV: // GL2GL3
273 case GL_UNSIGNED_SHORT_8_8_APPLE: // GL2
274 case GL_UNSIGNED_SHORT_8_8_REV_APPLE: // GL2
275 case GL_HALF_FLOAT:
276 // case GL_HALF_FLOAT_OES: // GLES2
277 return parent->slice(pos, length); // .asShortBuffer(); // slice and duplicate
278
279 case GL_FIXED:
280 case GL_INT: // GL2ES2
281 case GL_UNSIGNED_INT:
282 case GL_UNSIGNED_INT_8_8_8_8: // GL2GL3
283 case GL_UNSIGNED_INT_8_8_8_8_REV: // GL2GL3
284 case GL_UNSIGNED_INT_10_10_10_2: // GL2ES2
285 case GL_UNSIGNED_INT_2_10_10_10_REV: // GL2ES2
286 case GL_UNSIGNED_INT_24_8:
287 case GL_UNSIGNED_INT_10F_11F_11F_REV:
288 case GL_HILO16_NV: // GL2
289 case GL_UNSIGNED_INT_5_9_9_9_REV: // GL2ES3
290 case GL_SIGNED_HILO16_NV: // GL2
291 return parent->slice(pos, length); // .asIntBuffer(); // slice and duplicate may change byte order
292
293 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: // GL2ES3
294 return parent->slice(pos, length); // .asLongBuffer(); // slice and duplicate may change byte order
295 break;
296
297 case GL_FLOAT:
298 return parent->slice(pos, length); // .asFloatBuffer(); // slice and duplicate may change byte order
299
300 case GL_DOUBLE: // GL2GL3
301 return parent->slice(pos, length); // .asDoubleBuffer(); // slice and duplicate may change byte order
302
303 default: return nullptr;
304 }
305
306 }
307
308#endif
309
310 static GLint glGetInteger(GLenum pname) {
311 int tmp[] = { 0 };
312 glGetIntegerv(pname, tmp);
313 return tmp[0];
314 }
315
316 /**
317 * Returns the number of bytes required to read/write a memory buffer via OpenGL
318 * using the current GL pixel storage state and the given parameters.
319 *
320 * <p>This method is security critical, hence it throws an exception (fail-fast)
321 * in case of an invalid alignment. In case we forgot to handle
322 * proper values, please contact the maintainer.</p>
323 *
324 * @param glp the current GLProfile
325 * @param bytesPerPixel bytes per pixel, i.e. via {@link #bytesPerPixel(int, int)}.
326 * @param width in pixels
327 * @param height in pixels
328 * @param depth in pixels
329 * @param pack true for read mode GPU -> CPU (pack), otherwise false for write mode CPU -> GPU (unpack)
330 * @return required minimum size of the buffer in bytes
331 * @throws GLException if alignment is invalid. Please contact the maintainer if this is our bug.
332 */
333 static glmemsize_t byteSize(const GL& gl,
334 GLsizei bytesPerPixel, GLsizei width, GLsizei height, GLsizei depth,
335 bool pack) {
336 glmemsize_t width2 = 0;
337 glmemsize_t rowLength = 0;
338 glmemsize_t skipRows = 0;
339 glmemsize_t skipPixels = 0;
340 GLsizei alignment = 1;
341 glmemsize_t imageHeight = 0;
342 GLsizei skipImages = 0;
343
344 if (pack) {
345 alignment = glGetInteger(GL_PACK_ALIGNMENT); // es2, es3, gl3
346 if( gl.glProfile().isGL2ES3() ) {
347 rowLength = glGetInteger(GL_PACK_ROW_LENGTH); // es3, gl3
348 skipRows = glGetInteger(GL_PACK_SKIP_ROWS); // es3, gl3
349 skipPixels = glGetInteger(GL_PACK_SKIP_PIXELS); // es3, gl3
350 if (depth > 1 && gl.glProfile().isGL2GL3() && gl.version() >= Version1_2) {
351 imageHeight = glGetInteger(GL_PACK_IMAGE_HEIGHT); // gl3, GL_VERSION_1_2
352 skipImages = glGetInteger(GL_PACK_SKIP_IMAGES); // gl3, GL_VERSION_1_2
353 }
354 }
355 } else {
356 alignment = glGetInteger(GL_UNPACK_ALIGNMENT); // es2, es3, gl3
357 if( gl.glProfile().isGL2ES3() ) {
358 rowLength = glGetInteger(GL_UNPACK_ROW_LENGTH); // es3, gl3
359 skipRows = glGetInteger(GL_UNPACK_SKIP_ROWS); // es3, gl3
360 skipPixels = glGetInteger(GL_UNPACK_SKIP_PIXELS); // es3, gl3
361 if( depth > 1 &&
362 ( gl.glProfile().isGL3ES3() ||
363 ( gl.glProfile().isGL2GL3() && gl.version() >= Version1_2 )
364 )
365 ) {
366 imageHeight = glGetInteger(GL_UNPACK_IMAGE_HEIGHT);// es3, gl3, GL_VERSION_1_2
367 skipImages = glGetInteger(GL_UNPACK_SKIP_IMAGES); // es3, gl3, GL_VERSION_1_2
368 }
369 }
370 }
371
372 // Try to deal somewhat correctly with potentially invalid values
373 width2 = std::max<glmemsize_t>(0, width);
374 height = std::max<GLsizei>(1, height); // min 1D
375 depth = std::max<GLsizei>(1, depth ); // min 1 * imageSize
376 skipRows = std::max<glmemsize_t>(0, skipRows);
377 skipPixels = std::max<glmemsize_t>(0, skipPixels);
378 alignment = std::max<GLsizei>(1, alignment);
379 skipImages = std::max<GLsizei>(0, skipImages);
380
381 imageHeight = ( imageHeight > 0 ) ? imageHeight : height;
382 rowLength = ( rowLength > 0 ) ? rowLength : width2;
383
384 glmemsize_t rowLengthInBytes = rowLength * bytesPerPixel;
385 glmemsize_t skipBytes = skipPixels * bytesPerPixel;
386
387 switch(alignment) {
388 case 1:
389 break;
390 case 2:
391 case 4:
392 case 8: {
393 // x % 2n == x & (2n - 1)
394 glmemsize_t remainder = rowLengthInBytes & ( alignment - 1L );
395 if (remainder > 0) {
396 rowLengthInBytes += alignment - remainder;
397 }
398 remainder = skipBytes & ( alignment - 1L );
399 if (remainder > 0) {
400 skipBytes += alignment - remainder;
401 }
402 }
403 break;
404 default:
405 throw RenderException("Invalid alignment "+std::to_string(alignment)+", must be 2**n (1,2,4,8). Pls notify the maintainer in case this is our bug.", E_FILE_LINE);
406 }
407
408 /**
409 * skipImages, depth, skipPixels and skipRows are static offsets.
410 *
411 * skipImages and depth are in multiples of image size.
412 *
413 * skipBytes and rowLengthInBytes are aligned
414 *
415 * rowLengthInBytes is the aligned byte offset
416 * from line n to line n+1 at the same x-axis position.
417 */
418 return
419 skipBytes + // aligned skipPixels * bpp
420 ( skipImages + depth - 1 ) * imageHeight * rowLengthInBytes + // aligned whole images
421 ( skipRows + height - 1 ) * rowLengthInBytes + // aligned lines
422 width2 * bytesPerPixel; // last line
423 }
424
425 /**
426 * Returns the number of bytes required to read/write a memory buffer via OpenGL
427 * using the current GL pixel storage state and the given parameters.
428 *
429 * <p>This method is security critical, hence it throws an exception (fail-fast)
430 * in case either the format, type or alignment is unhandled. In case we forgot to handle
431 * proper values, please contact the maintainer.</p>
432 *
433 * <p> See {@link #bytesPerPixel(int, int)}. </p>
434 *
435 * @param gl the current GL object
436 *
437 * @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
438 *
439 * @param format must be one of (27) <br/>
440 * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
441 * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
442 * GL_RED GL_RED_INTEGER <br/>
443 * GL_GREEN GL_GREEN_INTEGER <br/>
444 * GL_BLUE GL_BLUE_INTEGER <br/>
445 * GL_ALPHA GL_LUMINANCE (12) <br/>
446 * <br/>
447 * GL_LUMINANCE_ALPHA GL_RG <br/>
448 * GL_RG_INTEGER GL_HILO_NV <br/>
449 * GL_SIGNED_HILO_NV (5) <br/>
450 * <br/>
451 * GL_YCBCR_422_APPLE <br/>
452 * <br/>
453 * GL_RGB GL_RGB_INTEGER <br/>
454 * GL_BGR GL_BGR_INTEGER (4)<br/>
455 * <br/>
456 * GL_RGBA GL_RGBA_INTEGER <br/>
457 * GL_BGRA GL_BGRA_INTEGER <br/>
458 * GL_ABGR_EXT (5)<br/>
459 *
460 * @param type must be one of (32) <br/>
461 * GL_BITMAP, <br/>
462 * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
463 * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
464 * <br/>
465 * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
466 * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
467 * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
468 * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
469 * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
470 * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
471 * <br/>
472 * GL_FIXED, GL_INT <br/>
473 * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
474 * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
475 * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
476 * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
477 * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
478 * <br/>
479 * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
480 * <br/>
481 * GL_FLOAT, GL_DOUBLE <br/>
482 *
483 * @param width in pixels
484 * @param height in pixels
485 * @param depth in pixels
486 * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
487 * @return required minimum size of the buffer in bytes
488 * @throws GLException if format, type or alignment is not handled. Please contact the maintainer if this is our bug.
489 */
490 static size_t byteSize(const GL& gl,
491 GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth,
492 bool pack)
493 {
494 if (width < 0) return 0;
495 if (height < 0) return 0;
496 if (depth < 0) return 0;
497
498 GLsizei bytesPerPixel_ = bytesPerPixel(format, type);
499 return byteSize(gl, bytesPerPixel_, width, height, depth, pack);
500 }
501
502 /**
503 * Returns the number of bytes required for one pixel with the the given OpenGL format and type.
504 *
505 * <p>This method is security critical, hence it throws an exception (fail-fast)
506 * in case either the format, type or alignment is unhandled. In case we forgot to handle
507 * proper values, please contact the maintainer.</p>
508 *
509 * <p> See {@link #componentCount(int)}. </p>
510 *
511 * @param format must be one of (27) <br/>
512 * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
513 * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
514 * GL_RED GL_RED_INTEGER <br/>
515 * GL_GREEN GL_GREEN_INTEGER <br/>
516 * GL_BLUE GL_BLUE_INTEGER <br/>
517 * GL_ALPHA GL_LUMINANCE (12) <br/>
518 * <br/>
519 * GL_LUMINANCE_ALPHA GL_RG <br/>
520 * GL_RG_INTEGER GL_HILO_NV <br/>
521 * GL_SIGNED_HILO_NV (5) <br/>
522 * <br/>
523 * GL_YCBCR_422_APPLE <br/>
524 * <br/>
525 * GL_RGB GL_RGB_INTEGER <br/>
526 * GL_BGR GL_BGR_INTEGER (4)<br/>
527 * <br/>
528 * GL_RGBA GL_RGBA_INTEGER <br/>
529 * GL_BGRA GL_BGRA_INTEGER <br/>
530 * GL_ABGR_EXT (5)<br/>
531 *
532 * @param type must be one of (32) <br/>
533 * GL_BITMAP, <br/>
534 * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
535 * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
536 * <br/>
537 * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
538 * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
539 * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
540 * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
541 * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
542 * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
543 * <br/>
544 * GL_FIXED, GL_INT <br/>
545 * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
546 * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
547 * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
548 * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
549 * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
550 * <br/>
551 * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
552 * <br/>
553 * GL_FLOAT, GL_DOUBLE <br/>
554 *
555 * @return required size of one pixel in bytes
556 * @throws GLException if format or type alignment is not handled. Please contact the maintainer if this is our bug.
557 */
558 static GLsizei bytesPerPixel(GLenum format, GLenum type) {
559 GLsizei compSize = 0;
560
561 GLsizei compCount = componentCount(format);
562
563 switch (type) /* 30 */ {
564 case GL_BITMAP: // GL2
565 if (GL_COLOR_INDEX == format || GL_STENCIL_INDEX == format) {
566 compSize = 1;
567 } else {
568 throw RenderException("BITMAP type only supported for format COLOR_INDEX and STENCIL_INDEX, not "+jau::to_hexstring(format), E_FILE_LINE);
569 }
570 break;
571 case GL_BYTE:
572 case GL_UNSIGNED_BYTE:
573 compSize = 1;
574 break;
575 case GL_SHORT:
576 case GL_UNSIGNED_SHORT:
577 case GL_HALF_FLOAT:
578 // case GL_HALF_FLOAT_OES: // GLES2
579 compSize = 2;
580 break;
581 case GL_FIXED:
582 case GL_INT: // GL2ES2
583 case GL_UNSIGNED_INT:
584 case GL_FLOAT:
585 compSize = 4;
586 break;
587 case GL_DOUBLE: // GL2GL3
588 compSize = 8;
589 break;
590
591 case GL_UNSIGNED_BYTE_3_3_2: // GL2GL3
592 case GL_UNSIGNED_BYTE_2_3_3_REV: // GL2GL3
593 compSize = 1;
594 compCount = 1;
595 break;
596 case GL_UNSIGNED_SHORT_5_6_5:
597 case GL_UNSIGNED_SHORT_5_6_5_REV: // GL2GL3
598 case GL_UNSIGNED_SHORT_4_4_4_4:
599 case GL_UNSIGNED_SHORT_4_4_4_4_REV: // GL2GL3
600 case GL_UNSIGNED_SHORT_5_5_5_1:
601 case GL_UNSIGNED_SHORT_1_5_5_5_REV: // GL2GL3
602 case GL_UNSIGNED_SHORT_8_8_APPLE: // GL2
603 case GL_UNSIGNED_SHORT_8_8_REV_APPLE: // GL2
604 compSize = 2;
605 compCount = 1;
606 break;
607 case GL_HILO16_NV: // GL2
608 case GL_SIGNED_HILO16_NV: // GL2
609 compSize = 2;
610 compCount = 2;
611 break;
612 case GL_UNSIGNED_INT_8_8_8_8: // GL2GL3
613 case GL_UNSIGNED_INT_8_8_8_8_REV: // GL2GL3
614 case GL_UNSIGNED_INT_10_10_10_2: // GL2ES2
615 case GL_UNSIGNED_INT_2_10_10_10_REV: // GL2ES2
616 case GL_UNSIGNED_INT_24_8:
617 case GL_UNSIGNED_INT_10F_11F_11F_REV:
618 case GL_UNSIGNED_INT_5_9_9_9_REV: // GL2ES3
619 compSize = 4;
620 compCount = 1;
621 break;
622 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: // GL2ES3
623 compSize = 8;
624 compCount = 1;
625 break;
626
627 default:
628 throw RenderException("type "+jau::to_hexstring(type)+"/"+"format "+jau::to_hexstring(format)+" not supported [yet], pls notify the maintainer in case this is our bug.", E_FILE_LINE);
629 }
630 return compCount * compSize;
631 }
632
633 /**
634 * Returns the number of components required for the given OpenGL format.
635 *
636 * <p>This method is security critical, hence it throws an exception (fail-fast)
637 * in case either the format, type or alignment is unhandled. In case we forgot to handle
638 * proper values, please contact the maintainer.</p>
639 *
640 * @param format must be one of (27) <br/>
641 * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
642 * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
643 * GL_RED GL_RED_INTEGER <br/>
644 * GL_GREEN GL_GREEN_INTEGER <br/>
645 * GL_BLUE GL_BLUE_INTEGER <br/>
646 * GL_ALPHA GL_LUMINANCE (12) <br/>
647 * <br/>
648 * GL_LUMINANCE_ALPHA GL_RG <br/>
649 * GL_RG_INTEGER GL_HILO_NV <br/>
650 * GL_SIGNED_HILO_NV (5) <br/>
651 * <br/>
652 * GL_YCBCR_422_APPLE <br/>
653 * <br/>
654 * GL_RGB GL_RGB_INTEGER <br/>
655 * GL_BGR GL_BGR_INTEGER (4)<br/>
656 * <br/>
657 * GL_RGBA GL_RGBA_INTEGER <br/>
658 * GL_BGRA GL_BGRA_INTEGER <br/>
659 * GL_ABGR_EXT (5)<br/>
660 *
661 * @return number of components required for the given OpenGL format
662 * @throws GLException if format is not handled. Please contact the maintainer if this is our bug.
663 */
664 static GLsizei componentCount(GLenum format) {
665 GLint compCount;
666
667 switch (format) /* 26 */ {
668 case GL_COLOR_INDEX: // GL2
669 case GL_STENCIL_INDEX: // GL2ES2
670 case GL_DEPTH_COMPONENT: // GL2ES2
671 case GL_DEPTH_STENCIL:
672 case GL_RED: // GL2ES2
673 case GL_RED_INTEGER: // GL2ES3
674 case GL_GREEN: // GL2ES3
675 case GL_GREEN_INTEGER: // GL2GL3
676 case GL_BLUE: // GL2ES3
677 case GL_BLUE_INTEGER: // GL2GL3
678 case GL_ALPHA:
679 case GL_LUMINANCE:
680 compCount = 1;
681 break;
682 case GL_LUMINANCE_ALPHA:
683 case GL_RG: // GL2ES2
684 case GL_RG_INTEGER: // GL2ES3
685 case GL_HILO_NV: // GL2
686 case GL_SIGNED_HILO_NV: // GL2
687 compCount = 2;
688 break;
689 case GL_RGB:
690 case GL_RGB_INTEGER: // GL2ES3
691 case GL_BGR:
692 case GL_BGR_INTEGER: // GL2GL3
693 compCount = 3;
694 break;
695 case GL_YCBCR_422_APPLE: // GL2
696 compCount = 3;
697 break;
698 case GL_RGBA:
699 case GL_RGBA_INTEGER: // GL2ES3
700 case GL_BGRA:
701 case GL_BGRA_INTEGER: // GL2GL3
702 case GL_ABGR_EXT: // GL2
703 compCount = 4;
704 break;
705 /* FIXME ??
706 case GL_HILO_NV:
707 elements = 2;
708 break; */
709 default:
710 throw RenderException("format "+jau::to_hexstring(format)+" not supported [yet], pls notify the maintainer in case this is our bug.", E_FILE_LINE);
711 }
712 return compCount;
713 }
714
715 /**@}*/
716
717 };
718}
719
720#endif // GAMP_GLBUFFERS_HPP_
#define E_FILE_LINE
OpenGL buffer related routines.
Definition GLBuffers.hpp:31
float float32_t
double float64_t
static constexpr GLsizei sizeOfGLType(GLenum glType)
Definition GLBuffers.hpp:99
GLsizeiptr glmemsize_t
Compatible with ssize_t.
Definition GLBuffers.hpp:26
static glmemsize_t byteSize(const GL &gl, GLsizei bytesPerPixel, GLsizei width, GLsizei height, GLsizei depth, bool pack)
Returns the number of bytes required to read/write a memory buffer via OpenGL using the current GL pi...
static size_t byteSize(const GL &gl, GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, bool pack)
Returns the number of bytes required to read/write a memory buffer via OpenGL using the current GL pi...
static constexpr bool isGLTypeFixedPoint(GLenum glType)
Definition GLBuffers.hpp:61
static GLsizei bytesPerPixel(GLenum format, GLenum type)
Returns the number of bytes required for one pixel with the the given OpenGL format and type.
static constexpr bool isSignedGLType(GLenum glType)
Definition GLBuffers.hpp:41
static GLsizei componentCount(GLenum format)
Returns the number of components required for the given OpenGL format.
static GLint glGetInteger(GLenum pname)
constexpr GLenum glType() noexcept
Definition GLTypes.hpp:46
static constexpr jau::util::VersionNumber Version1_2
Version 1.2, i.e.
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.