diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp')
6 files changed, 145 insertions, 74 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java index e9853cc31..9a9b94fa9 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java @@ -31,6 +31,8 @@ import java.nio.Buffer; import java.nio.ByteBuffer; import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2ES3; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; @@ -43,13 +45,16 @@ import com.jogamp.opengl.util.texture.TextureData; * {@link GLPixelBufferProvider} produces a {@link GLPixelBuffer}. * </p> * <p> - * You may use {@link #defaultProvider}. + * You may use {@link #defaultProviderNoRowStride}. * </p> */ public class GLPixelBuffer { /** Allows user to interface with another toolkit to define {@link GLPixelAttributes} and memory buffer to produce {@link TextureData}. */ public static interface GLPixelBufferProvider { + /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. */ + boolean getAllowRowStride(); + /** Called first to determine {@link GLPixelAttributes}. */ GLPixelAttributes getAttributes(GL gl, int componentCount); @@ -87,23 +92,49 @@ public class GLPixelBuffer { GLPixelBuffer initSingleton(int componentCount, int width, int height, int depth, boolean pack); } - /** - * Default {@link GLPixelBufferProvider} utilizing best match for {@link GLPixelAttributes} - * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}. - */ - public static GLPixelBufferProvider defaultProvider = new GLPixelBufferProvider() { + public static class DefaultGLPixelBufferProvider implements GLPixelBufferProvider { + private final boolean allowRowStride; + + /** + * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. + * See {@link #getAllowRowStride()} and {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}. + */ + public DefaultGLPixelBufferProvider(boolean allowRowStride) { + this.allowRowStride = allowRowStride; + } + + @Override + public boolean getAllowRowStride() { return allowRowStride; } @Override public GLPixelAttributes getAttributes(GL gl, int componentCount) { final GLContext ctx = gl.getContext(); final int dFormat, dType; - if(gl.isGL2GL3() && 3 == componentCount) { + if( 1 == componentCount ) { + if( gl.isGL3ES3() ) { + // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core + dFormat = GL2ES2.GL_RED; + } else { + // ALPHA is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility + dFormat = GL2ES2.GL_ALPHA; + } + dType = GL.GL_UNSIGNED_BYTE; + } else if( 3 == componentCount ) { dFormat = GL.GL_RGB; dType = GL.GL_UNSIGNED_BYTE; + } else if( 4 == componentCount ) { + int _dFormat = ctx.getDefaultPixelDataFormat(); + final int dComps = GLBuffers.componentCount(_dFormat); + if( dComps == componentCount ) { + dFormat = _dFormat; + dType = ctx.getDefaultPixelDataType(); + } else { + dFormat = GL.GL_RGBA; + dType = GL.GL_UNSIGNED_BYTE; + } } else { - dFormat = ctx.getDefaultPixelDataFormat(); - dType = ctx.getDefaultPixelDataType(); + throw new GLException("Unsupported componentCount "+componentCount+", contact maintainer to enhance"); } return new GLPixelAttributes(componentCount, dFormat, dType); } @@ -117,15 +148,29 @@ public class GLPixelBuffer { @Override public GLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) { if( minByteSize > 0 ) { - return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(minByteSize)); + return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(minByteSize), getAllowRowStride()); } else { int[] tmp = { 0 }; final int byteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, width, height, depth, pack); - return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(byteSize)); + return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(byteSize), getAllowRowStride()); } } - }; + } + + /** + * Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>false</code>, + * utilizing best match for {@link GLPixelAttributes} + * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}. + */ + public static GLPixelBufferProvider defaultProviderNoRowStride = new DefaultGLPixelBufferProvider(false); + /** + * Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>true</code>, + * utilizing best match for {@link GLPixelAttributes} + * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}. + */ + public static GLPixelBufferProvider defaultProviderWithRowStride = new DefaultGLPixelBufferProvider(true); + /** Pixel attributes. */ public static class GLPixelAttributes { /** Undefined instance of {@link GLPixelAttributes}, having componentCount:=0, format:=0 and type:= 0. */ @@ -199,6 +244,9 @@ public class GLPixelBuffer { /** Buffer element size in bytes. */ public final int bufferElemSize; + /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. See {@link #requiresNewBuffer(GL, int, int, int)}. */ + public final boolean allowRowStride; + private boolean disposed = false; public StringBuilder toString(StringBuilder sb) { @@ -212,8 +260,17 @@ public class GLPixelBuffer { public String toString() { return "GLPixelBuffer["+toString(null).toString()+"]"; } - - public GLPixelBuffer(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, Buffer buffer) { + + /** + * @param pixelAttributes the desired {@link GLPixelAttributes} + * @param width in pixels + * @param height in pixels + * @param depth in pixels + * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU + * @param buffer the backing array + * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}. + */ + public GLPixelBuffer(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, Buffer buffer, boolean allowRowStride) { this.pixelAttributes = pixelAttributes; this.width = width; this.height = height; @@ -222,13 +279,18 @@ public class GLPixelBuffer { this.buffer = buffer; this.byteSize = Buffers.remainingBytes(buffer); this.bufferElemSize = Buffers.sizeOfBufferElem(buffer); + this.allowRowStride = allowRowStride; } + /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. */ + public final boolean getAllowRowStride() { return allowRowStride; } + /** Is not {@link #dispose() disposed} and has {@link #byteSize} > 0. */ public boolean isValid() { return !disposed && 0 < byteSize; } + /** See {@link Buffer#rewind()}. */ public Buffer rewind() { return buffer.rewind(); } @@ -243,10 +305,22 @@ public class GLPixelBuffer { return buffer.position( bytePos / bufferElemSize ); } + /** Returns the byte capacity of the {@link #buffer}. */ + public int capacity() { + return buffer.capacity() * bufferElemSize; + } + + /** Returns the byte limit of the {@link #buffer}. */ + public int limit() { + return buffer.limit() * bufferElemSize; + } + + /** See {@link Buffer#flip()}. */ public Buffer flip() { return buffer.flip(); } + /** See {@link Buffer#clear()}. */ public Buffer clear() { return buffer.clear(); } @@ -259,17 +333,37 @@ public class GLPixelBuffer { * </p> * <p> * The minimum required byte size equals to <code>minByteSize</code>, if > 0, - * otherwise utilize {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean) GLBuffers.sizeof(..)} - * to calculate it. + * otherwise {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean) GLBuffers.sizeof(..)} + * is being used to calculate it. This value is referred to <i>newByteSize</i>. + * </p> + * <p> + * If <code>{@link #allowRowStride} = false</code>, + * method returns <code>true</code> if the <i>newByteSize</i> > <i>currentByteSize</i> + * or the <code>newWidth</code> != <code>currentWidth</code>. + * </p> + * <p> + * If <code>{@link #allowRowStride} = true</code>, see {@link GLPixelBufferProvider#getAllowRowStride()}, + * method returns <code>true</code> only if the <i>newByteSize</i> > <i>currentByteSize</i>. + * Assuming user utilizes the row-stride when dealing w/ the data, i.e. {@link GL2ES3#GL_PACK_ROW_LENGTH}. * </p> * @param gl the corresponding current GL context object * @param newWidth new width in pixels * @param newHeight new height in pixels - * @param minByteSize if > 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore. + * @param newByteSize if > 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore. * @see GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) */ - public boolean requiresNewBuffer(GL gl, int newWidth, int newHeight, int minByteSize) { - return !isValid() || byteSize < minByteSize; + public boolean requiresNewBuffer(GL gl, int newWidth, int newHeight, int newByteSize) { + if( !isValid() ) { + return true; + } + if( 0 >= newByteSize ) { + final int[] tmp = { 0 }; + newByteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, newWidth, newHeight, 1, true); + } + if( allowRowStride ) { + return byteSize < newByteSize; + } + return byteSize < newByteSize || width != newWidth; } /** Dispose resources. See {@link #isValid()}. */ diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java index cd6a8ac72..65d1b6906 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java @@ -63,7 +63,7 @@ public class GLReadBufferUtil { * @param write2Texture true if readPixel's TextureData shall be written to a 2d Texture */ public GLReadBufferUtil(boolean alpha, boolean write2Texture) { - this(GLPixelBuffer.defaultProvider, alpha, write2Texture); + this(GLPixelBuffer.defaultProviderNoRowStride, alpha, write2Texture); } public GLReadBufferUtil(GLPixelBufferProvider pixelBufferProvider, boolean alpha, boolean write2Texture) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java index df1bbdf26..1f5bb6acc 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java @@ -33,7 +33,6 @@ import java.nio.Buffer; import java.nio.IntBuffer; import javax.media.opengl.GL; -import javax.media.opengl.GL2GL3; import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.util.GLPixelBuffer; @@ -57,8 +56,6 @@ public class AWTGLPixelBuffer extends GLPixelBuffer { public static final GLPixelAttributes awtPixelAttributesIntRGBA4 = new GLPixelAttributes(4, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE); public static final GLPixelAttributes awtPixelAttributesIntRGB3 = new GLPixelAttributes(3, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE); - /** Allow {@link GL2GL3#GL_PACK_ROW_LENGTH}, or {@link GL2GL3#GL_UNPACK_ROW_LENGTH}. See {@link #requiresNewBuffer(GL, int, int, int)}. */ - public final boolean allowRowStride; /** The underlying {@link BufferedImage}. */ public final BufferedImage image; @@ -74,35 +71,10 @@ public class AWTGLPixelBuffer extends GLPixelBuffer { */ public AWTGLPixelBuffer(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, BufferedImage image, Buffer buffer, boolean allowRowStride) { - super(pixelAttributes, width, height, depth, pack, buffer); - this.allowRowStride = allowRowStride; + super(pixelAttributes, width, height, depth, pack, buffer, allowRowStride); this.image = image; } - /** - * {@inheritDoc} - * <p> - * If <code>{@link #allowRowStride} = false</code>, - * method returns <code>true</code> if the new size ≠ current size. - * </p> - * <p> - * If <code>{@link #allowRowStride} = true</code>, see {@link AWTGLPixelBufferProvider#AWTGLPixelBufferProvider(boolean)}, - * method returns <code>true</code> only if the new size > current size. Assuming user utilizes the row-stride - * when dealing w/ the data, i.e. {@link GL2GL3#GL_PACK_ROW_LENGTH}. - * </p> - */ - @Override - public boolean requiresNewBuffer(GL gl, int newWidth, int newHeight, int minByteSize) { - if( !isValid() ) { - return true; - } - if( allowRowStride && gl.isGL2GL3() ) { - return width < newWidth || height < newHeight; - } else { - return width != newWidth || height != newHeight; - } - } - @Override public void dispose() { image.flush(); @@ -121,17 +93,20 @@ public class AWTGLPixelBuffer extends GLPixelBuffer { /** * Provider for {@link AWTGLPixelBuffer} instances. */ - public static class AWTGLPixelBufferProvider implements GLPixelBufferProvider { - /** Allow {@link GL2GL3#GL_PACK_ROW_LENGTH}, or {@link GL2GL3#GL_UNPACK_ROW_LENGTH}. */ - public final boolean allowRowStride; + public static class AWTGLPixelBufferProvider implements GLPixelBufferProvider { + private final boolean allowRowStride; /** - * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}. + * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. + * See {@link #getAllowRowStride()} and {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}. */ public AWTGLPixelBufferProvider(boolean allowRowStride) { - this.allowRowStride = allowRowStride; + this.allowRowStride = allowRowStride; } @Override + public boolean getAllowRowStride() { return allowRowStride; } + + @Override public GLPixelAttributes getAttributes(GL gl, int componentCount) { return 4 == componentCount ? awtPixelAttributesIntRGBA4 : awtPixelAttributesIntRGB3; } @@ -197,7 +172,7 @@ public class AWTGLPixelBuffer extends GLPixelBuffer { final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer ); - return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, allowRowStride); + return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, getAllowRowStride()); } /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link AWTGLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */ diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java index a689e318c..092e2abf0 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java @@ -46,7 +46,7 @@ public class AWTGLReadBufferUtil extends GLReadBufferUtil { * @param alpha */ public AWTGLReadBufferUtil(GLProfile glp, boolean alpha) { - super(new AWTGLPixelBuffer.AWTGLPixelBufferProvider( glp.isGL2GL3() /* allowRowStride */ ), alpha, false); + super(new AWTGLPixelBuffer.AWTGLPixelBufferProvider( glp.isGL2GL3() || glp.isGL3ES3() /* allowRowStride */ ), alpha, false); } public AWTGLPixelBuffer getAWTGLPixelBuffer() { return (AWTGLPixelBuffer)this.getPixelBuffer(); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java index dec1b43cf..afc5bf70c 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java @@ -353,11 +353,11 @@ public class TextureData { public GLPixelAttributes getPixelAttributes() { return pixelAttributes; } - /** Returns the intended OpenGL pixel format of the texture data. */ + /** Returns the intended OpenGL pixel format of the texture data using {@link #getPixelAttributes()}. */ public int getPixelFormat() { return pixelAttributes.format; } - /** Returns the intended OpenGL pixel type of the texture data. */ + /** Returns the intended OpenGL pixel type of the texture data using {@link #getPixelAttributes()}. */ public int getPixelType() { return pixelAttributes.type; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java index 14ceb6421..df8ac5934 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java @@ -54,6 +54,7 @@ import java.util.List; import javax.media.opengl.GL; import javax.media.opengl.GL2; +import javax.media.opengl.GL2ES2; import javax.media.opengl.GL2GL3; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; @@ -62,6 +63,7 @@ import javax.media.opengl.GLProfile; import jogamp.opengl.Debug; import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; import com.jogamp.opengl.util.texture.spi.DDSImage; import com.jogamp.opengl.util.texture.spi.JPEGImage; import com.jogamp.opengl.util.texture.spi.NetPbmTextureWriter; @@ -1228,8 +1230,9 @@ public class TextureIO { TextureData data) throws IOException { if (DDS.equals(IOUtil.getFileSuffix(file))) { // See whether the DDS writer can handle this TextureData - int pixelFormat = data.getPixelFormat(); - int pixelType = data.getPixelType(); + final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); + final int pixelFormat = pixelAttribs.format; + final int pixelType = pixelAttribs.type; if (pixelType != GL.GL_BYTE && pixelType != GL.GL_UNSIGNED_BYTE) { throw new IOException("DDS writer only supports byte / unsigned byte textures"); @@ -1279,8 +1282,9 @@ public class TextureIO { if (SGI.equals(fileSuffix) || SGI_RGB.equals(fileSuffix)) { // See whether the SGI writer can handle this TextureData - int pixelFormat = data.getPixelFormat(); - int pixelType = data.getPixelType(); + final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); + final int pixelFormat = pixelAttribs.format; + final int pixelType = pixelAttribs.type; if ((pixelFormat == GL.GL_RGB || pixelFormat == GL.GL_RGBA) && (pixelType == GL.GL_BYTE || @@ -1321,8 +1325,9 @@ public class TextureIO { TextureData data) throws IOException { if (TGA.equals(IOUtil.getFileSuffix(file))) { // See whether the TGA writer can handle this TextureData - int pixelFormat = data.getPixelFormat(); - int pixelType = data.getPixelType(); + final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); + final int pixelFormat = pixelAttribs.format; + final int pixelType = pixelAttribs.type; if ((pixelFormat == GL.GL_RGB || pixelFormat == GL.GL_RGBA || pixelFormat == GL2.GL_BGR || @@ -1369,34 +1374,31 @@ public class TextureIO { public boolean write(File file, TextureData data) throws IOException { if (PNG.equals(IOUtil.getFileSuffix(file))) { // See whether the PNG writer can handle this TextureData - int pixelFormat = data.getPixelFormat(); - int pixelType = data.getPixelType(); - boolean reversedChannels; - int bytesPerPixel; + final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); + final int pixelFormat = pixelAttribs.format; + final int pixelType = pixelAttribs.type; + final int bytesPerPixel = pixelAttribs.bytesPerPixel; + final boolean reversedChannels; switch(pixelFormat) { + case GL.GL_ALPHA: case GL.GL_LUMINANCE: + case GL2ES2.GL_RED: reversedChannels=false; - bytesPerPixel=1; break; case GL.GL_RGB: reversedChannels=false; - bytesPerPixel=3; break; case GL.GL_RGBA: reversedChannels=false; - bytesPerPixel=4; break; case GL2.GL_BGR: reversedChannels=true; - bytesPerPixel=3; break; case GL.GL_BGRA: reversedChannels=true; - bytesPerPixel=4; break; default: reversedChannels=false; - bytesPerPixel=-1; break; } if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) && |