JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
GLPixelBuffer.java
Go to the documentation of this file.
1/**
2 * Copyright 2013 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.opengl.util;
29
30import java.nio.Buffer;
31import java.nio.ByteBuffer;
32
33import com.jogamp.nativewindow.util.PixelFormat;
34import com.jogamp.opengl.GL;
35import com.jogamp.opengl.GL2ES2;
36import com.jogamp.opengl.GL2ES3;
37import com.jogamp.opengl.GL2GL3;
38import com.jogamp.opengl.GLContext;
39import com.jogamp.opengl.GLException;
40import com.jogamp.opengl.GLProfile;
41
42import com.jogamp.common.nio.Buffers;
43import com.jogamp.opengl.util.texture.TextureData;
44
45/**
46 * OpenGL pixel data buffer, allowing user to provide buffers via their {@link GLPixelBufferProvider} implementation.
47 * <p>
48 * {@link GLPixelBufferProvider} produces a {@link GLPixelBuffer}.
49 * </p>
50 * <p>
51 * You may use {@link #defaultProviderNoRowStride}.
52 * </p>
53 */
54public class GLPixelBuffer {
55
56 /** Allows user to interface with another toolkit to define {@link GLPixelAttributes} and memory buffer to produce {@link TextureData}. */
57 public static interface GLPixelBufferProvider {
58 /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. */
60
61 /**
62 * Returns RGB[A] {@link GLPixelAttributes} matching {@link GL}, {@code componentCount} and {@code pack}.
63 *
64 * @param gl the corresponding current {@link GL} context object
65 * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
66 * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
67 * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
68 */
69 GLPixelAttributes getAttributes(GL gl, int componentCount, boolean pack);
70
71 /**
72 * Returns the host {@link PixelFormat.Composition} matching {@link GL} and {@code componentCount}
73 * if required by implementation, otherwise {@code null}.
74 *
75 * @param glp the corresponding current {@link GL} context object
76 * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
77 */
78 PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount);
79
80 /**
81 * Allocates a new {@link GLPixelBuffer} object.
82 * <p>
83 * The minimum required {@link Buffer#remaining() remaining} byte size equals to <code>minByteSize</code>, if &gt; 0,
84 * otherwise utilize {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean)}
85 * to calculate it.
86 * </p>
87 *
88 * @param gl the corresponding current {@link GL} context object
89 * @param hostPixComp host {@link PixelFormat pixel format}, i.e. of the source or sink depending on {@code pack},
90 * e.g. fetched via {@link #getHostPixelComp(GLProfile, int)}.
91 * If {@code null}, {@code pixelAttributes} instance maybe used or an exception is thrown,
92 * depending on implementation semantics.
93 * @param pixelAttributes the desired {@link GLPixelAttributes}, e.g. fetched via {@link #getAttributes(GL, int, boolean)}
94 * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
95 * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
96 * @param width in pixels
97 * @param height in pixels
98 * @param depth in pixels
99 * @param minByteSize if &gt; 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.
100 * @see #getHostPixelComp(GLProfile, int)
101 * @see #getAttributes(GL, int, boolean)
102 */
104 boolean pack, int width, int height, int depth, int minByteSize);
105 }
106
107 /** Single {@link GLPixelBuffer} provider. */
109 /**
110 * {@inheritDoc}
111 * <p>
112 * Being called to gather the initial {@link GLPixelBuffer},
113 * or a new replacement {@link GLPixelBuffer} if {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
114 * </p>
115 */
116 @Override
118 boolean pack, int width, int height, int depth, int minByteSize);
119
120 /**
121 * Return the last {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated} {@link GLPixelBuffer}
122 * matching the given parameter.
123 * <p>
124 * May return {@code null} if none has been allocated yet.
125 * </p>
126 * <p>
127 * Returned {@link GLPixelBuffer} may be {@link GLPixelBuffer#isValid() invalid}.
128 * </p>
129 * @param hostPixComp host {@link PixelFormat pixel format}, i.e. of the source or sink depending on {@code pack},
130 * e.g. fetched via {@link #getHostPixelComp(GLProfile, int)}.
131 * If {@code null}, {@code pixelAttributes} instance maybe used or an exception is thrown,
132 * depending on implementation semantics.
133 * @param pixelAttributes the desired {@link GLPixelAttributes}, e.g. fetched via {@link #getAttributes(GL, int, boolean)}
134 * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
135 * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
136 */
138 /**
139 * Initializes the single {@link GLPixelBuffer} w/ a given size,
140 * if not yet {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}.
141 *
142 * @param glp
143 * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
144 * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
145 * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
146 * @param width
147 * @param height
148 * @param depth
149 * @return the newly initialized single {@link GLPixelBuffer}, or null if already allocated.
150 */
151 GLPixelBuffer initSingleton(GLProfile glp, int componentCount, boolean pack, int width, int height, int depth);
152
153 /** Dispose all resources.*/
154 void dispose();
155 }
156
158 private final boolean allowRowStride;
159
160 /**
161 * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not.
162 * See {@link #getAllowRowStride()} and {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
163 */
164 public DefaultGLPixelBufferProvider(final boolean allowRowStride) {
165 this.allowRowStride = allowRowStride;
166 }
167
168 @Override
169 public boolean getAllowRowStride() { return allowRowStride; }
170
171 @Override
172 public GLPixelAttributes getAttributes(final GL gl, final int componentCount, final boolean pack) {
173 final GLPixelAttributes res = GLPixelAttributes.convert(gl, componentCount, pack);
174 if( null == res ) {
175 throw new GLException("Unsupported componentCount "+componentCount+", contact maintainer to enhance");
176 } else {
177 return res;
178 }
179 }
180
181 /**
182 * {@inheritDoc}
183 * <p>
184 * Returns {@code null}!
185 * </p>
186 */
187 @Override
188 public PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount) {
189 return null;
190 }
191
192 /**
193 * {@inheritDoc}
194 * <p>
195 * Returns an NIO {@link ByteBuffer}.
196 * </p>
197 */
198 @Override
200 final boolean pack, final int width, final int height, final int depth, final int minByteSize) {
201 // unused: hostPixComp
202 if( minByteSize > 0 ) {
203 return new GLPixelBuffer(pixelAttributes, pack, width, height, depth, Buffers.newDirectByteBuffer(minByteSize), getAllowRowStride());
204 } else {
205 final int[] tmp = { 0 };
207 return new GLPixelBuffer(pixelAttributes, pack, width, height, depth, Buffers.newDirectByteBuffer(byteSize), getAllowRowStride());
208 }
209 }
210 }
211
212 /**
213 * Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>false</code>,
214 * utilizing best match for {@link GLPixelAttributes}
215 * and {@link GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocating} a {@link ByteBuffer}.
216 */
218
219 /**
220 * Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>true</code>,
221 * utilizing best match for {@link GLPixelAttributes}
222 * and {@link GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocating} a {@link ByteBuffer}.
223 */
225
226 /** Pixel attributes. */
227 public static class GLPixelAttributes {
228 /** Undefined instance of {@link GLPixelAttributes}, having componentCount:=0, format:=0 and type:= 0. */
229 public static final GLPixelAttributes UNDEF = new GLPixelAttributes(null, PixelFormat.LUMINANCE, 0, 0, true, false);
230
231 /**
232 * Returns the matching {@link PixelFormat} for the given GL format and type if exists,
233 * otherwise returns <code>null</code>.
234 */
235 public static final PixelFormat getPixelFormat(final int glFormat, final int glDataType) {
236 PixelFormat pixFmt = null;
237
238 switch(glFormat) {
239 case GL.GL_ALPHA:
240 case GL.GL_LUMINANCE:
241 case GL2ES2.GL_RED:
242 pixFmt = PixelFormat.LUMINANCE;
243 break;
244 case GL.GL_RGB:
245 switch(glDataType) {
247 pixFmt = PixelFormat.RGB565;
248 break;
250 pixFmt = PixelFormat.BGR565;
251 break;
252 case GL.GL_UNSIGNED_BYTE:
253 pixFmt = PixelFormat.RGB888;
254 break;
255 }
256 break;
257 case GL.GL_RGBA:
258 switch(glDataType) {
260 pixFmt = PixelFormat.RGBA5551;
261 break;
263 pixFmt = PixelFormat.ABGR1555;
264 break;
266 // fall through intended
267 case GL.GL_UNSIGNED_BYTE:
268 pixFmt = PixelFormat.RGBA8888;
269 break;
271 pixFmt = PixelFormat.ABGR8888;
272 break;
273 }
274 break;
275 case GL.GL_BGR:
276 if( GL.GL_UNSIGNED_BYTE == glDataType ) {
277 pixFmt = PixelFormat.BGR888;
278 }
279 break;
280 case GL.GL_BGRA:
281 switch(glDataType) {
283 pixFmt = PixelFormat.ARGB8888;
284 break;
286 // fall through intended
287 case GL.GL_UNSIGNED_BYTE:
288 pixFmt = PixelFormat.BGRA8888;
289 break;
290 }
291 break;
292 }
293 return pixFmt;
294 }
295
296 /**
297 * Returns the matching {@link GLPixelAttributes} for the given byte sized RGBA {@code componentCount} and {@link GL} if exists,
298 * otherwise returns {@code null}.
299 *
300 * @param gl the corresponding current {@link GL} context object
301 * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
302 * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
303 * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
304 */
305 public static GLPixelAttributes convert(final GL gl, final int componentCount, final boolean pack) {
306 final int dFormat, dType;
307 final boolean glesReadMode = pack && gl.isGLES();
308
309 if( 1 == componentCount && !glesReadMode ) {
310 if( gl.isGL3ES3() ) {
311 // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core
312 dFormat = GL2ES2.GL_RED;
313 } else {
314 // ALPHA is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
315 dFormat = GL.GL_ALPHA;
316 }
317 dType = GL.GL_UNSIGNED_BYTE;
318 } else if( 3 == componentCount && !glesReadMode ) {
319 dFormat = GL.GL_RGB;
320 dType = GL.GL_UNSIGNED_BYTE;
321 } else if( 4 == componentCount || glesReadMode ) {
322 final GLContext ctx = gl.getContext();
323 final int _dFormat = ctx.getDefaultPixelDataFormat();
324 final int _dComps = GLBuffers.componentCount(_dFormat);
325 if( _dComps == componentCount || 4 == _dComps ) { // accept if desired component count or 4 components
326 // pre-check whether default is supported by implementation
327 final int _dType = ctx.getDefaultPixelDataType();
328 final PixelFormat _pixFmt = getPixelFormat(_dFormat, _dType);
329 if( null != _pixFmt) {
330 return new GLPixelAttributes(null, _pixFmt, _dFormat, _dType, pack, true);
331 }
332 if( GLContext.DEBUG ) {
333 System.err.println("GLPixelAttributes.convert("+gl.getGLProfile()+", comps "+componentCount+", pack "+pack+
334 "): GL-impl default unsupported: "+
335 "[fmt 0x"+Integer.toHexString(_dFormat)+", type 0x"+Integer.toHexString(_dType)+"]: Using std RGBA+UBYTE");
336 Thread.dumpStack();
337 }
338 // fall-through intended to set dFormat/dType to std values
339 }
340 dFormat = GL.GL_RGBA;
341 dType = GL.GL_UNSIGNED_BYTE;
342 } else {
343 return null;
344 }
345 return new GLPixelAttributes(dFormat, dType);
346 }
347
348 /**
349 * Returns the matching {@link GLPixelAttributes} for the given {@link GLProfile}, {@link PixelFormat} and {@code pack} if exists,
350 * otherwise returns {@code null}.
351 * @param glp the corresponding {@link GLProfile}
352 * @param pixFmt the to be matched {@link PixelFormat pixel format}
353 * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
354 * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
355 */
356 public static final GLPixelAttributes convert(final GLProfile glp, final PixelFormat pixFmt, final boolean pack) {
357 final int[] df = new int[1];
358 final int[] dt = new int[1];
359 convert(glp, pixFmt, pack, df, dt);
360 if( 0 != df[0] ) {
361 return new GLPixelAttributes(null, pixFmt, df[0], dt[0], true /* not used */, true);
362 }
363 return null;
364 }
365 private static final int convert(final GLProfile glp, final PixelFormat pixFmt, final boolean pack,
366 final int[] dfRes, final int[] dtRes) {
367 final boolean glesReadMode = pack && glp.isGLES();
368 int df = 0; // format
369 int dt = GL.GL_UNSIGNED_BYTE; // data type
370 switch(pixFmt) {
371 case LUMINANCE:
372 if( !glesReadMode ) {
373 if( glp.isGL3ES3() ) {
374 // RED is supported on ES3 and >= GL3 [core]; ALPHA/LUMINANCE is deprecated on core
375 df = GL2ES2.GL_RED;
376 } else {
377 // ALPHA/LUMINANCE is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
378 df = GL.GL_LUMINANCE;
379 }
380 }
381 break;
382 case RGB565:
383 if( glp.isGL2GL3() ) {
384 df = GL.GL_RGB; dt = GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV;
385 }
386 break;
387 case BGR565:
388 if( glp.isGL2GL3() ) {
389 df = GL.GL_RGB; dt = GL.GL_UNSIGNED_SHORT_5_6_5;
390 }
391 break;
392 case RGBA5551:
393 if( glp.isGL2GL3() ) {
394 df = GL.GL_RGBA; dt = GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV;
395 }
396 break;
397 case ABGR1555:
398 if( glp.isGL2GL3() ) {
399 df = GL.GL_RGBA; dt = GL.GL_UNSIGNED_SHORT_5_5_5_1;
400 }
401 break;
402 case RGB888:
403 if( !glesReadMode ) {
404 df = GL.GL_RGB;
405 }
406 break;
407 case BGR888:
408 if( glp.isGL2GL3() ) {
409 df = GL.GL_BGR;
410 }
411 break;
412 case RGBx8888:
413 case RGBA8888:
414 df = GL.GL_RGBA;
415 break;
416 case ABGR8888:
417 if( glp.isGL2GL3() ) {
418 df = GL.GL_RGBA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
419 }
420 break;
421 case ARGB8888:
422 if( glp.isGL2GL3() ) {
423 df = GL.GL_BGRA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
424 }
425 break;
426 case BGRx8888:
427 case BGRA8888:
428 if( glp.isGL2GL3() ) { // FIXME: or if( !glesReadMode ) ? BGRA n/a on GLES
429 df = GL.GL_BGRA;
430 }
431 break;
432 }
433 dfRes[0] = df;
434 dtRes[0] = dt;
435 return df;
436 }
437
438 /** The OpenGL pixel data format */
439 public final int format;
440 /** The OpenGL pixel data type */
441 public final int type;
442
443 /** {@link PixelFormat} describing the {@link PixelFormat.Composition component} layout */
444 public final PixelFormat pfmt;
445
446 @Override
447 public final int hashCode() {
448 // 31 * x == (x << 5) - x
449 int hash = pfmt.hashCode();
450 hash = ((hash << 5) - hash) + format;
451 return ((hash << 5) - hash) + type;
452 }
453
454 @Override
455 public final boolean equals(final Object obj) {
456 if(this == obj) { return true; }
457 if( obj instanceof GLPixelAttributes ) {
458 final GLPixelAttributes other = (GLPixelAttributes) obj;
459 return format == other.format &&
460 type == other.type &&
461 pfmt.equals(other.pfmt);
462 } else {
463 return false;
464 }
465 }
466
467 /**
468 * Create a new {@link GLPixelAttributes} instance based on GL format and type.
469 * @param dataFormat GL data format
470 * @param dataType GL data type
471 * @throws GLException if {@link PixelFormat} could not be determined, see {@link #getPixelFormat(int, int)}.
472 */
473 public GLPixelAttributes(final int dataFormat, final int dataType) throws GLException {
474 this(null, null, dataFormat, dataType, true /* not used */, true);
475 }
476
477 /**
478 * Create a new {@link GLPixelAttributes} instance based on {@link GLProfile}, {@link PixelFormat} and {@code pack}.
479 * @param glp the corresponding {@link GLProfile}
480 * @param pixFmt the to be matched {@link PixelFormat pixel format}
481 * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
482 * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
483 * @throws GLException if GL format or type could not be determined, see {@link #convert(GLProfile, PixelFormat, boolean)}.
484 */
485 public GLPixelAttributes(final GLProfile glp, final PixelFormat pixFmt, final boolean pack) throws GLException {
486 this(glp, pixFmt, 0, 0, pack, true);
487 }
488
489 private GLPixelAttributes(final GLProfile glp, final PixelFormat pixFmt,
490 final int dataFormat, final int dataType, final boolean pack, final boolean checkArgs) throws GLException {
491 if( checkArgs && ( 0 == dataFormat || 0 == dataType ) ) {
492 if( null == pixFmt || null == glp ) {
493 throw new GLException("Zero format and/or type w/o pixFmt or glp: "+this);
494 }
495 final int[] df = new int[1];
496 final int[] dt = new int[1];
497 if( 0 == convert(glp, pixFmt, pack, df, dt) ) {
498 throw new GLException("Could not find format and type for "+pixFmt+" and "+glp+", "+this);
499 }
500 this.format = df[0];
501 this.type = dt[0];
502 this.pfmt = pixFmt;
503 } else {
504 this.format = dataFormat;
505 this.type = dataType;
506 this.pfmt = null != pixFmt ? pixFmt : getPixelFormat(dataFormat, dataType);
507 if( null == this.pfmt ) {
508 throw new GLException("Could not find PixelFormat for format and/or type: "+this);
509 }
510 }
511 if( checkArgs ) {
512 final int bytesPerPixel = GLBuffers.bytesPerPixel(this.format, this.type);
513 if( 0 == bytesPerPixel ) {
514 throw new GLException("Zero bytesPerPixel: "+this);
515 }
516 }
517 }
518
519 @Override
520 public String toString() {
521 return "PixelAttributes[fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", "+pfmt+"]";
522 }
523 }
524
525 /** The {@link GLPixelAttributes}. */
527 /**
528 * Width in pixels, representing {@link #buffer}'s {@link #byteSize}.
529 * <p>
530 * May not represent actual image width as user may re-use buffer for different dimensions, see {@link #requiresNewBuffer(GL, int, int, int)}.
531 * </p>
532 */
533 public final int width;
534 /**
535 * Height in pixels, representing {@link #buffer}'s {@link #byteSize}.
536 * <p>
537 * May not represent actual image height as user may re-use buffer for different dimensions, see {@link #requiresNewBuffer(GL, int, int, int)}.
538 * </p>
539 */
540 public final int height;
541 /** Depth in pixels. */
542 public final int depth;
543 /**
544 * Data packing direction.
545 * <p>{@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.</p>
546 * <p>{@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.</p>
547 */
548 public final boolean pack;
549 /** Byte size of the buffer. Actually the number of {@link Buffer#remaining()} bytes when passed in ctor. */
550 public final int byteSize;
551 /**
552 * Buffer holding the pixel data. If {@link #rewind()}, it holds <code>byteSize</code> {@link Buffer#remaining()} bytes.
553 * <p>
554 * By default the {@link Buffer} is a {@link ByteBuffer}, due to {@link DefProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int)}.
555 * However, other {@link GLPixelBufferProvider} may utilize different {@link Buffer} types.
556 * </p>
557 */
558 public final Buffer buffer;
559 /** Buffer element size in bytes. */
560 public final int bufferElemSize;
561
562 /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. See {@link #requiresNewBuffer(GL, int, int, int)}. */
563 public final boolean allowRowStride;
564
565 private boolean disposed = false;
566
567 public StringBuilder toString(StringBuilder sb) {
568 if(null == sb) {
569 sb = new StringBuilder();
570 }
571 sb.append(pixelAttributes).append(", dim ").append(width).append("x").append(height).append("x").append(depth).append(", pack ").append(pack)
572 .append(", disposed ").append(disposed).append(", valid ").append(isValid())
573 .append(", buffer[bytes ").append(byteSize).append(", elemSize ").append(bufferElemSize).append(", ").append(buffer).append("]");
574 return sb;
575 }
576 @Override
577 public String toString() {
578 return "GLPixelBuffer["+toString(null).toString()+"]";
579 }
580
581 /**
582 * @param pixelAttributes the desired {@link GLPixelAttributes}
583 * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
584 * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
585 * @param width in pixels
586 * @param height in pixels
587 * @param depth in pixels
588 * @param buffer the backing array
589 * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}.
590 * @param hostPixelComp the host {@link PixelFormat.Composition}
591 */
592 public GLPixelBuffer(final GLPixelAttributes pixelAttributes, final boolean pack, final int width, final int height, final int depth, final Buffer buffer, final boolean allowRowStride) {
593 this.pixelAttributes = pixelAttributes;
594 this.width = width;
595 this.height = height;
596 this.depth = depth;
597 this.pack = pack;
598 this.buffer = buffer;
599 this.byteSize = Buffers.remainingBytes(buffer);
600 this.bufferElemSize = Buffers.sizeOfBufferElem(buffer);
601 this.allowRowStride = allowRowStride;
602 }
603
604 /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. */
605 public final boolean getAllowRowStride() { return allowRowStride; }
606
607 /** Is not {@link #dispose() disposed} and has {@link #byteSize} &gt; 0. */
608 public boolean isValid() {
609 return !disposed && 0 < byteSize;
610 }
611
612 /** See {@link Buffer#rewind()}. */
613 public Buffer rewind() {
614 return buffer.rewind();
615 }
616
617 /** Returns the byte position of the {@link #buffer}. */
618 public int position() {
619 return buffer.position() * bufferElemSize;
620 }
621
622 /** Sets the byte position of the {@link #buffer}. */
623 public Buffer position(final int bytePos) {
624 return buffer.position( bytePos / bufferElemSize );
625 }
626
627 /** Returns the byte capacity of the {@link #buffer}. */
628 public int capacity() {
629 return buffer.capacity() * bufferElemSize;
630 }
631
632 /** Returns the byte limit of the {@link #buffer}. */
633 public int limit() {
634 return buffer.limit() * bufferElemSize;
635 }
636
637 /** See {@link Buffer#flip()}. */
638 public Buffer flip() {
639 return buffer.flip();
640 }
641
642 /** See {@link Buffer#clear()}. */
643 public Buffer clear() {
644 return buffer.clear();
645 }
646
647 /**
648 * Returns true, if {@link #isValid() invalid} or implementation requires a new buffer based on the new size
649 * due to pixel alignment or byte size, otherwise false.
650 * <p>
651 * It is assumed that <code>pixelAttributes</code>, <code>depth</code> and <code>pack</code> stays the same!
652 * </p>
653 * <p>
654 * The minimum required byte size equals to <code>minByteSize</code>, if &gt; 0,
655 * otherwise {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean) GLBuffers.sizeof(..)}
656 * is being used to calculate it. This value is referred to <i>newByteSize</i>.
657 * </p>
658 * <p>
659 * If <code>{@link #allowRowStride} = false</code>,
660 * method returns <code>true</code> if the <i>newByteSize</i> &gt; <i>currentByteSize</i>
661 * or the <code>newWidth</code> != <code>currentWidth</code>.
662 * </p>
663 * <p>
664 * If <code>{@link #allowRowStride} = true</code>, see {@link GLPixelBufferProvider#getAllowRowStride()},
665 * method returns <code>true</code> only if the <i>newByteSize</i> &gt; <i>currentByteSize</i>.
666 * Assuming user utilizes the row-stride when dealing w/ the data, i.e. {@link GL2ES3#GL_PACK_ROW_LENGTH}.
667 * </p>
668 * @param gl the corresponding current GL context object
669 * @param newWidth new width in pixels
670 * @param newHeight new height in pixels
671 * @param newByteSize if &gt; 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.
672 * @see GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int)
673 */
674 public boolean requiresNewBuffer(final GL gl, final int newWidth, final int newHeight, int newByteSize) {
675 if( !isValid() ) {
676 return true;
677 }
678 if( 0 >= newByteSize ) {
679 final int[] tmp = { 0 };
680 newByteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.pfmt.comp.bytesPerPixel(), newWidth, newHeight, 1, true);
681 }
682 if( allowRowStride ) {
683 return byteSize < newByteSize;
684 }
685 return byteSize < newByteSize || width != newWidth;
686 }
687
688 /** Dispose resources. See {@link #isValid()}. */
689 public void dispose() {
690 disposed = true;
691 buffer.clear();
692 }
693}
694
Abstraction for an OpenGL rendering context.
Definition: GLContext.java:74
abstract int getDefaultPixelDataFormat()
Get the default pixel data format, as required by e.g.
static final boolean DEBUG
Definition: GLContext.java:76
abstract int getDefaultPixelDataType()
Get the default pixel data type, as required by e.g.
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
Specifies the the OpenGL profile.
Definition: GLProfile.java:77
final boolean isGL3ES3()
Indicates whether this profile is capable of GL3ES3.
final boolean isGLES()
Indicates whether this profile is capable of GLES.
final boolean isGL2GL3()
Indicates whether this profile is capable of GL2GL3.
Utility routines for dealing with direct buffers.
Definition: GLBuffers.java:60
static final int componentCount(final int format)
Returns the number of components required for the given OpenGL format.
Definition: GLBuffers.java:693
static final int sizeof(final GL gl, final int tmp[], final int bytesPerPixel, int width, int height, int depth, final boolean pack)
Returns the number of bytes required to read/write a memory buffer via OpenGL using the current GL pi...
Definition: GLBuffers.java:364
GLPixelBuffer allocate(final GL gl, final PixelFormat.Composition hostPixComp, final GLPixelAttributes pixelAttributes, final boolean pack, final int width, final int height, final int depth, final int minByteSize)
Allocates a new GLPixelBuffer object.The minimum required remaining byte size equals to minByteSize,...
boolean getAllowRowStride()
Allow GL2ES3#GL_PACK_ROW_LENGTH, or GL2ES2#GL_UNPACK_ROW_LENGTH.
PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount)
Returns the host PixelFormat.Composition matching GL and componentCount if required by implementation...
GLPixelAttributes getAttributes(final GL gl, final int componentCount, final boolean pack)
Returns RGB[A] GLPixelAttributes matching GL, componentCount and pack.
static final PixelFormat getPixelFormat(final int glFormat, final int glDataType)
Returns the matching PixelFormat for the given GL format and type if exists, otherwise returns null.
static final GLPixelAttributes convert(final GLProfile glp, final PixelFormat pixFmt, final boolean pack)
Returns the matching GLPixelAttributes for the given GLProfile, PixelFormat and pack if exists,...
final PixelFormat pfmt
PixelFormat describing the component layout
GLPixelAttributes(final GLProfile glp, final PixelFormat pixFmt, final boolean pack)
Create a new GLPixelAttributes instance based on GLProfile, PixelFormat and pack.
final int format
The OpenGL pixel data format.
GLPixelAttributes(final int dataFormat, final int dataType)
Create a new GLPixelAttributes instance based on GL format and type.
static GLPixelAttributes convert(final GL gl, final int componentCount, final boolean pack)
Returns the matching GLPixelAttributes for the given byte sized RGBA componentCount and GL if exists,...
static final GLPixelAttributes UNDEF
Undefined instance of GLPixelAttributes, having componentCount:=0, format:=0 and type:= 0.
OpenGL pixel data buffer, allowing user to provide buffers via their GLPixelBufferProvider implementa...
int position()
Returns the byte position of the buffer.
int capacity()
Returns the byte capacity of the buffer.
final int byteSize
Byte size of the buffer.
final int width
Width in pixels, representing buffer's byteSize.
int limit()
Returns the byte limit of the buffer.
Buffer flip()
See Buffer#flip().
void dispose()
Dispose resources.
static final GLPixelBufferProvider defaultProviderWithRowStride
Default GLPixelBufferProvider with GLPixelBufferProvider#getAllowRowStride() == true,...
static final GLPixelBufferProvider defaultProviderNoRowStride
Default GLPixelBufferProvider with GLPixelBufferProvider#getAllowRowStride() == false,...
final boolean allowRowStride
Allow GL2ES3#GL_PACK_ROW_LENGTH, or GL2ES2#GL_UNPACK_ROW_LENGTH.
final int depth
Depth in pixels.
final int height
Height in pixels, representing buffer's byteSize.
GLPixelBuffer(final GLPixelAttributes pixelAttributes, final boolean pack, final int width, final int height, final int depth, final Buffer buffer, final boolean allowRowStride)
StringBuilder toString(StringBuilder sb)
final int bufferElemSize
Buffer element size in bytes.
Buffer rewind()
See Buffer#rewind().
final boolean getAllowRowStride()
Allow GL2ES3#GL_PACK_ROW_LENGTH, or GL2ES2#GL_UNPACK_ROW_LENGTH.
final GLPixelAttributes pixelAttributes
The GLPixelAttributes.
Buffer clear()
See Buffer#clear().
boolean requiresNewBuffer(final GL gl, final int newWidth, final int newHeight, int newByteSize)
Returns true, if invalid or implementation requires a new buffer based on the new size due to pixel a...
boolean isValid()
Is not disposed and has byteSize > 0.
final boolean pack
Data packing direction.
Buffer position(final int bytePos)
Sets the byte position of the buffer.
final Buffer buffer
Buffer holding the pixel data.
LUMINANCE
Stride is 8 bits, 8 bits per pixel, 1 component of 8 bits.
BGR565
Stride is 16 bits, 16 bits per pixel, 3 discrete components.
ABGR8888
Stride is 32 bits, 32 bits per pixel, 4 uniform components of 8 bits.
BGRA8888
Stride is 32 bits, 32 bits per pixel, 4 uniform components of 8 bits.
final Composition comp
Unique Pixel Composition, i.e.
BGR888
Stride is 24 bits, 24 bits per pixel, 3 uniform components of of 8 bits.
RGBA8888
Stride is 32 bits, 32 bits per pixel, 4 uniform components of 8 bits.
RGBA5551
Stride is 16 bits, 16 bits per pixel, 4 discrete components.
RGB565
Stride is 16 bits, 16 bits per pixel, 3 discrete components.
ABGR1555
Stride is 16 bits, 16 bits per pixel, 4 discrete components.
ARGB8888
Stride is 32 bits, 32 bits per pixel, 4 uniform components of 8 bits.
RGB888
Stride 24 bits, 24 bits per pixel, 3 uniform components of 8 bits.
int bytesPerPixel()
Number of bytes per pixel, i.e.
static final int GL_RED
GL_ES_VERSION_3_0, GL_VERSION_1_1, GL_VERSION_1_0, GL_NV_blend_equation_advanced, GL_EXT_texture_rg A...
Definition: GL2ES2.java:596
static final int GL_UNSIGNED_SHORT_5_6_5_REV
GL_VERSION_1_2 Define "GL_UNSIGNED_SHORT_5_6_5_REV" with expression '0x8364', CType: int
Definition: GL2GL3.java:453
static final int GL_UNSIGNED_INT_8_8_8_8
GL_VERSION_1_2, GL_EXT_packed_pixels Alias for: GL_UNSIGNED_INT_8_8_8_8_EXT Define "GL_UNSIGNED_INT_...
Definition: GL2GL3.java:366
static final int GL_UNSIGNED_INT_8_8_8_8_REV
GL_VERSION_1_2 Define "GL_UNSIGNED_INT_8_8_8_8_REV" with expression '0x8367', CType: int
Definition: GL2GL3.java:368
static final int GL_UNSIGNED_SHORT_1_5_5_5_REV
GL_VERSION_1_2, GL_EXT_read_format_bgra Alias for: GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT Define "GL_UNSI...
Definition: GL2GL3.java:465
boolean isGLES()
Indicates whether this GL object conforms to one of the OpenGL ES profiles, see isGLES1(),...
boolean isGL3ES3()
Indicates whether this GL object conforms to a GL3ES3 compatible profile.
GLProfile getGLProfile()
Returns the GLProfile associated with this GL object.
GLContext getContext()
Returns the GLContext associated which this GL object.
static final int GL_BGRA
GL_VERSION_1_2, GL_IMG_read_format, GL_APPLE_texture_format_BGRA8888, GL_EXT_texture_format_BGRA8888,...
Definition: GL.java:404
static final int GL_RGB
GL_ES_VERSION_2_0, GL_VERSION_1_1, GL_VERSION_1_0, GL_VERSION_ES_1_0 Define "GL_RGB" with expression ...
Definition: GL.java:374
static final int GL_LUMINANCE
GL_ES_VERSION_2_0, GL_VERSION_1_0, GL_VERSION_ES_1_0 Define "GL_LUMINANCE" with expression '0x1909',...
Definition: GL.java:216
static final int GL_UNSIGNED_SHORT_5_5_5_1
GL_ES_VERSION_2_0, GL_VERSION_1_2, GL_VERSION_ES_1_0, GL_EXT_packed_pixels Alias for: GL_UNSIGNED_SHO...
Definition: GL.java:462
static final int GL_BGR
GL_VERSION_1_2, GL_EXT_bgra Alias for: GL_BGR_EXT Define "GL_BGR" with expression '0x80E0',...
Definition: GL.java:399
static final int GL_ALPHA
GL_ES_VERSION_2_0, GL_VERSION_1_1, GL_VERSION_1_0, GL_VERSION_ES_1_0 Define "GL_ALPHA" with expressio...
Definition: GL.java:643
static final int GL_UNSIGNED_SHORT_5_6_5
GL_ES_VERSION_2_0, GL_VERSION_1_2, GL_VERSION_ES_1_0 Define "GL_UNSIGNED_SHORT_5_6_5" with expression...
Definition: GL.java:328
static final int GL_RGBA
GL_ES_VERSION_2_0, GL_VERSION_1_1, GL_VERSION_1_0, GL_VERSION_ES_1_0 Define "GL_RGBA" with expression...
Definition: GL.java:150
static final int GL_UNSIGNED_BYTE
GL_ES_VERSION_2_0, GL_VERSION_1_1, GL_VERSION_1_0, GL_VERSION_ES_1_0 Define "GL_UNSIGNED_BYTE" with e...
Definition: GL.java:284
Allows user to interface with another toolkit to define GLPixelAttributes and memory buffer to produc...
GLPixelBuffer allocate(GL gl, PixelFormat.Composition hostPixComp, GLPixelAttributes pixelAttributes, boolean pack, int width, int height, int depth, int minByteSize)
Allocates a new GLPixelBuffer object.
boolean getAllowRowStride()
Allow GL2ES3#GL_PACK_ROW_LENGTH, or GL2ES2#GL_UNPACK_ROW_LENGTH.
GLPixelAttributes getAttributes(GL gl, int componentCount, boolean pack)
Returns RGB[A] GLPixelAttributes matching GL, componentCount and pack.
PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount)
Returns the host PixelFormat.Composition matching GL and componentCount if required by implementation...
GLPixelBuffer initSingleton(GLProfile glp, int componentCount, boolean pack, int width, int height, int depth)
Initializes the single GLPixelBuffer w/ a given size, if not yet allocated.
GLPixelBuffer getSingleBuffer(PixelFormat.Composition hostPixelComp, GLPixelAttributes pixelAttributes, boolean pack)
Return the last allocated GLPixelBuffer matching the given parameter.
GLPixelBuffer allocate(GL gl, PixelFormat.Composition hostPixComp, GLPixelAttributes pixelAttributes, boolean pack, int width, int height, int depth, int minByteSize)
Allocates a new GLPixelBuffer object.The minimum required remaining byte size equals to minByteSize,...