From d354cf767182c27f44ad4c00d2e975f8d689daa8 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 26 May 2014 19:15:42 +0200 Subject: Bug 1009: Make FBObject's sampling sink format compatible w/ sampling source if possible (ES3 spec requirement) Make FBObject's sampling sink format compatible w/ sampling source if possible, i.e. for all GL profiles but ES1 and ES2. This is an ES3 spec requirement: For ES3, sampling-sink colorbuffer format must be equal w/ the sampling-source Colorbuffer. ES3 BlitFramebuffer Requirements: OpenGL ES 3.0.2 p194: 4.3.2 Copying Pixels: If SAMPLE_BUFFERS for the read framebuffer is greater than zero, no copy is performed and an INVALID_OPERATION error is generated if the formats of the read and draw framebuffers are not identical or if the source and destination rectangles are not defined with the same (X0, Y 0) and (X1, Y 1) bounds. Texture and Renderbuffer format details: ES2 Base iFormat: OpenGL ES 2.0.24 p66: 3.7.1 Texture Image Specification, Table 3.8 - ALPHA, LUMINANCE, LUMINANCE_ALPHA, RGB, RGBA ES3 Base iFormat: OpenGL ES 3.0.2 p125: 3.8.3 Texture Image Specification, Table 3.11 - ALPHA, LUMINANCE, LUMINANCE_ALPHA, RGB, RGBA DEPTH_COMPONENT, STENCIL_COMPONENT, RED, RG ES3 Required Texture and Renderbuffer iFormat: OpenGL ES 3.0.2 p126: 3.8.3 Texture Image Specification - RGBA32I, RGBA32UI, RGBA16I, RGBA16UI, RGBA8, RGBA8I, RGBA8UI, SRGB8_ALPHA8, RGB10_A2, RGB10_A2UI, RGBA4, and RGB5_A1. - RGB8 and RGB565. - RG32I, RG32UI, RG16I, RG16UI, RG8, RG8I, and RG8UI. - R32I, R32UI, R16I, R16UI, R8, R8I, and R8UI. +++ Our implementation shall attempt to use the same format for the sampling-source and -sink wherever possible, e.g. GL2ES3 (excluding ES1 and ES2)! --- src/jogl/classes/com/jogamp/opengl/FBObject.java | 114 +++++++++++++++++++---- 1 file changed, 97 insertions(+), 17 deletions(-) diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java index 33751eab9..a9b54097f 100644 --- a/src/jogl/classes/com/jogamp/opengl/FBObject.java +++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java @@ -550,21 +550,52 @@ public class FBObject { * *

Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.

* - * @param glp the chosen {@link GLProfile} + * @param gl the used {@link GLContext}'s {@link GL} object * @param alpha set to true if you request alpha channel, otherwise false; * @param width texture width * @param height texture height * @return the created and uninitialized color {@link TextureAttachment} */ - public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height) { - return createColorTextureAttachment(glp, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + public static final TextureAttachment createColorTextureAttachment(GL gl, boolean alpha, int width, int height) { + return createColorTextureAttachment(gl, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); } /** * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, * selecting the texture data type and format automatically. + *

+ * For GLES3, sampling-sink format must be equal w/ the sampling-source {@link Colorbuffer}, + * see details below. Implementation aligns w/ {@link #createColorAttachment(boolean)} + * and is enforced via {@link #sampleSinkFormatMismatch(GL)}. + *

+ *

+ * ES3 BlitFramebuffer Requirements: OpenGL ES 3.0.2 p194: 4.3.2 Copying Pixels + *

+     * If SAMPLE_BUFFERS for the read framebuffer is greater than zero, no copy
+     * is performed and an INVALID_OPERATION error is generated if the formats of
+     * the read and draw framebuffers are not identical or if the source and destination
+     * rectangles are not defined with the same (X0, Y 0) and (X1, Y 1) bounds.
+     * 
+ * Texture and Renderbuffer format details: + *
+     * ES2 Base iFormat: OpenGL ES 2.0.24 p66: 3.7.1 Texture Image Specification, Table 3.8
+     *   ALPHA, LUMINANCE, LUMINANCE_ALPHA, RGB, RGBA
+     *
+     * ES3 Base iFormat: OpenGL ES 3.0.2 p125: 3.8.3 Texture Image Specification, Table 3.11
+     *   ALPHA, LUMINANCE, LUMINANCE_ALPHA, RGB, RGBA
+     *   DEPTH_COMPONENT, STENCIL_COMPONENT, RED, RG
      *
-     * @param glp the chosen {@link GLProfile}
+     * ES3 Required Texture and Renderbuffer iFormat: OpenGL ES 3.0.2 p126: 3.8.3 Texture Image Specification
+     *   - RGBA32I, RGBA32UI, RGBA16I, RGBA16UI, RGBA8, RGBA8I,
+     *     RGBA8UI, SRGB8_ALPHA8, RGB10_A2, RGB10_A2UI, RGBA4, and
+     *     RGB5_A1.
+     *   - RGB8 and RGB565.
+     *   - RG32I, RG32UI, RG16I, RG16UI, RG8, RG8I, and RG8UI.
+     *   - R32I, R32UI, R16I, R16UI, R8, R8I, and R8UI.
+     * 
+ *

+ * + * @param gl the used {@link GLContext}'s {@link GL} object * @param alpha set to true if you request alpha channel, otherwise false; * @param width texture width * @param height texture height @@ -574,10 +605,14 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return the created and uninitialized color {@link TextureAttachment} */ - public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height, + public static final TextureAttachment createColorTextureAttachment(GL gl, boolean alpha, int width, int height, int magFilter, int minFilter, int wrapS, int wrapT) { final int textureInternalFormat, textureDataFormat, textureDataType; - if(glp.isGLES()) { + if(gl.isGLES3()) { + textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; + textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataType = GL.GL_UNSIGNED_BYTE; + } else if(gl.isGLES()) { textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; textureDataType = GL.GL_UNSIGNED_BYTE; @@ -743,6 +778,26 @@ public class FBObject { return p>=0 ? getColorbuffer(p) : null; } + /** + * Returns true if any attached {@link Colorbuffer} uses alpha, + * otherwise false. + */ + public final boolean hasAttachmentUsingAlpha() { + final int caCount = getColorAttachmentCount(); + boolean hasAlpha = false; + for(int i=0; i @@ -1142,7 +1197,7 @@ public class FBObject { */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException { return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, - createColorTextureAttachment(gl.getGLProfile(), alpha, width, height)); + createColorTextureAttachment(gl, alpha, width, height)); } /** @@ -1164,7 +1219,7 @@ public class FBObject { */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, - createColorTextureAttachment(gl.getGLProfile(), alpha, width, height, magFilter, minFilter, wrapS, wrapT)); + createColorTextureAttachment(gl, alpha, width, height, magFilter, minFilter, wrapS, wrapT)); } /** @@ -1194,12 +1249,18 @@ public class FBObject { /** * Creates a {@link ColorAttachment}, selecting the format automatically. + *

+ * For GLES3, sampling-sink {@link Colorbuffer} format must be equal w/ the sampling-source {@link Colorbuffer}. + * Implementation aligns w/ {@link #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)} + * and is enforced via {@link #sampleSinkFormatMismatch(GL)}. + *

* * @param alpha set to true if you request alpha channel, otherwise false; * @return uninitialized ColorAttachment instance describing the new attached colorbuffer */ public final ColorAttachment createColorAttachment(boolean alpha) { final int internalFormat; + if( rgba8Avail ) { internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ; } else { @@ -1591,7 +1652,7 @@ public class FBObject { samplingSinkTexture.magFilter, samplingSinkTexture.minFilter, samplingSinkTexture.wrapS, samplingSinkTexture.wrapT); } else { - colbuf = createColorTextureAttachment(gl.getGLProfile(), true, width, height); + colbuf = createColorTextureAttachment(gl, true, width, height); } } attachColorbuffer(gl, attachmentPoint, colbuf); @@ -1944,6 +2005,19 @@ public class FBObject { return depthMismatch || stencilMismatch; } + /** + * For GLES3, sampling-sink {@link Colorbuffer} format must be equal w/ the sampling-source {@link Colorbuffer}. + * Implementation aligns w/ {@link #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)} + * and {@link #createColorAttachment(boolean)}. + */ + private final boolean sampleSinkFormatMismatch(final GL gl) { + if( null != samplingSinkTexture && getColorAttachmentCount() > 0 && gl.isGL2ES3() ) { + final Attachment ca = (Attachment)getColorbuffer(0); // should be at attachment-point 0 + return ( null != ca && ca.format != samplingSinkTexture.format ) || + hasAlpha(samplingSinkTexture.format) != hasAttachmentUsingAlpha(); + } + return false; + } /** * Manually reset the MSAA sampling sink, if used. @@ -1980,16 +2054,17 @@ public class FBObject { samplingSink.init(gl, width, height, 0); } + boolean sampleSinkFormatMismatch = sampleSinkFormatMismatch(gl); boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch(); boolean sampleSinkTexMismatch = sampleSinkTexMismatch(); boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch(); /** if(DEBUG) { System.err.println("FBObject.resetSamplingSink.0: \n\tTHIS "+this+",\n\tSINK "+samplesSink+ - "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); + "\n\t format "+sampleSinkFormatMismatch+", size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); } */ - if(!sampleSinkSizeMismatch && !sampleSinkTexMismatch && !sampleSinkDepthStencilMismatch) { + if(!sampleSinkFormatMismatch && !sampleSinkSizeMismatch && !sampleSinkTexMismatch && !sampleSinkDepthStencilMismatch) { // all properties match .. return; } @@ -1998,19 +2073,23 @@ public class FBObject { if(DEBUG) { System.err.println("FBObject.resetSamplingSink: BEGIN\n\tTHIS "+this+",\n\tSINK "+samplingSink+ - "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); + "\n\t format "+sampleSinkFormatMismatch+", size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); } if( sampleSinkDepthStencilMismatch ) { samplingSink.detachAllRenderbuffer(gl); } - if( sampleSinkSizeMismatch ) { + if( sampleSinkFormatMismatch ) { + samplingSink.detachAllColorbuffer(gl); + samplingSinkTexture = null; + } else if( sampleSinkSizeMismatch ) { samplingSink.reset(gl, width, height); } if(null == samplingSinkTexture) { - samplingSinkTexture = samplingSink.attachTexture2D(gl, 0, true); + boolean hasAlpha = hasAttachmentUsingAlpha(); + samplingSinkTexture = samplingSink.attachTexture2D(gl, 0, hasAlpha); } else if( 0 == samplingSinkTexture.getName() ) { samplingSinkTexture.setSize(width, height); samplingSink.attachColorbuffer(gl, 0, samplingSinkTexture); @@ -2023,17 +2102,18 @@ public class FBObject { } } + sampleSinkFormatMismatch = sampleSinkFormatMismatch(gl); sampleSinkSizeMismatch = sampleSinkSizeMismatch(); sampleSinkTexMismatch = sampleSinkTexMismatch(); sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch(); - if(sampleSinkSizeMismatch || sampleSinkTexMismatch || sampleSinkDepthStencilMismatch) { + if(sampleSinkFormatMismatch || sampleSinkSizeMismatch || sampleSinkTexMismatch || sampleSinkDepthStencilMismatch) { throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplingSink+ - "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); + "\n\t format "+sampleSinkFormatMismatch+", size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); } if(DEBUG) { System.err.println("FBObject.resetSamplingSink: END\n\tTHIS "+this+",\n\tSINK "+samplingSink+ - "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); + "\n\t format "+sampleSinkFormatMismatch+", size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); } } -- cgit v1.2.3