1 /** 2 * Copyright 2010 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 */ 28 package com.jogamp.opengl.test.junit.jogl.acore; 29 30 import com.jogamp.opengl.FBObject; 31 import com.jogamp.opengl.FBObject.TextureAttachment; 32 import com.jogamp.opengl.util.GLArrayDataServer; 33 import com.jogamp.opengl.util.GLReadBufferUtil; 34 import com.jogamp.opengl.util.PMVMatrix; 35 import com.jogamp.opengl.util.glsl.ShaderCode; 36 import com.jogamp.opengl.util.glsl.ShaderProgram; 37 import com.jogamp.opengl.util.glsl.ShaderState; 38 import com.jogamp.opengl.util.texture.TextureIO; 39 import com.jogamp.opengl.FBObject.Attachment.Type; 40 import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; 41 import com.jogamp.opengl.test.junit.util.MiscUtils; 42 import com.jogamp.opengl.test.junit.util.NEWTGLContext; 43 import com.jogamp.opengl.test.junit.util.UITestCase; 44 45 import java.io.IOException; 46 47 import com.jogamp.nativewindow.NativeSurface; 48 import com.jogamp.opengl.GL; 49 import com.jogamp.opengl.GL2ES2; 50 import com.jogamp.opengl.GL2GL3; 51 import com.jogamp.opengl.GLCapabilities; 52 import com.jogamp.opengl.GLDrawable; 53 import com.jogamp.opengl.GLProfile; 54 import com.jogamp.opengl.GLUniformData; 55 import com.jogamp.opengl.fixedfunc.GLMatrixFunc; 56 57 import org.junit.Assert; 58 import org.junit.Test; 59 import org.junit.FixMethodOrder; 60 import org.junit.runners.MethodSorters; 61 62 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 63 public class TestFBOMRTNEWT01 extends UITestCase { 64 static long durationPerTest = 10*40*2; // ms 65 66 @Test test01()67 public void test01() throws InterruptedException { 68 final int step = 4; 69 final int width = 800; 70 final int height = 600; 71 // preset .. 72 if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { 73 System.err.println("Test requires GL2/GL3 profile."); 74 return; 75 } 76 final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow( 77 new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true); 78 final GLDrawable drawable = winctx.context.getGLDrawable(); 79 final GL2GL3 gl = winctx.context.getGL().getGL2GL3(); 80 // gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) ).getGL2GL3(); 81 System.err.println(winctx.context); 82 83 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 84 // test code .. 85 final ShaderState st = new ShaderState(); 86 // st.setVerbose(true); 87 88 final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", 89 "shader/bin", "fbo-mrt-1", true); 90 final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", 91 "shader/bin", "fbo-mrt-1", true); 92 vp0.defaultShaderCustomization(gl, true, true); 93 fp0.defaultShaderCustomization(gl, true, true); 94 final ShaderProgram sp0 = new ShaderProgram(); 95 sp0.add(gl, vp0, System.err); 96 sp0.add(gl, fp0, System.err); 97 Assert.assertTrue(0 != sp0.program()); 98 Assert.assertTrue(!sp0.inUse()); 99 Assert.assertTrue(!sp0.linked()); 100 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 101 st.attachShaderProgram(gl, sp0, false); 102 103 final ShaderCode vp1 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", 104 "shader/bin", "fbo-mrt-2", true); 105 final ShaderCode fp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", 106 "shader/bin", "fbo-mrt-2", true); 107 vp1.defaultShaderCustomization(gl, true, true); 108 fp1.defaultShaderCustomization(gl, true, true); 109 final ShaderProgram sp1 = new ShaderProgram(); 110 sp1.add(gl, vp1, System.err); 111 sp1.add(gl, fp1, System.err); 112 Assert.assertTrue(0 != sp1.program()); 113 Assert.assertTrue(!sp1.inUse()); 114 Assert.assertTrue(!sp1.linked()); 115 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 116 st.attachShaderProgram(gl, sp1, true); 117 118 final PMVMatrix pmvMatrix = new PMVMatrix(); 119 final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); 120 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 121 st.ownUniform(pmvMatrixUniform); 122 st.uniform(gl, pmvMatrixUniform); 123 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 124 125 final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); 126 // st.bindAttribLocation(gl, 0, vertices0); 127 vertices0.putf(0); vertices0.putf(1); vertices0.putf(0); 128 vertices0.putf(1); vertices0.putf(1); vertices0.putf(0); 129 vertices0.putf(0); vertices0.putf(0); vertices0.putf(0); 130 vertices0.putf(1); vertices0.putf(0); vertices0.putf(0); 131 vertices0.seal(gl, true); 132 st.ownAttribute(vertices0, true); 133 vertices0.enableBuffer(gl, false); 134 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 135 136 final GLArrayDataServer colors0 = GLArrayDataServer.createGLSL("gca_Colors", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); 137 // st.bindAttribLocation(gl, 1, colors0); 138 colors0.putf(1); colors0.putf(0); colors0.putf(1); colors0.putf(1); 139 colors0.putf(0); colors0.putf(0); colors0.putf(1); colors0.putf(1); 140 colors0.putf(0); colors0.putf(0); colors0.putf(0); colors0.putf(1); 141 colors0.putf(0); colors0.putf(1); colors0.putf(1); colors0.putf(1); 142 colors0.seal(gl, true); 143 st.ownAttribute(colors0, true); 144 colors0.enableBuffer(gl, false); 145 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 146 147 final GLUniformData texUnit0 = new GLUniformData("gcs_TexUnit0", 0); 148 st.ownUniform(texUnit0); 149 st.uniform(gl, texUnit0); 150 final GLUniformData texUnit1 = new GLUniformData("gcs_TexUnit1", 1); 151 st.ownUniform(texUnit1); 152 st.uniform(gl, texUnit1); 153 154 final GLArrayDataServer texCoords0 = GLArrayDataServer.createGLSL("gca_TexCoords", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); 155 // st.bindAttribLocation(gl, 2, texCoords0); 156 texCoords0.putf(0f); texCoords0.putf(1f); 157 texCoords0.putf(1f); texCoords0.putf(1f); 158 texCoords0.putf(0f); texCoords0.putf(0f); 159 texCoords0.putf(1f); texCoords0.putf(0f); 160 texCoords0.seal(gl, true); 161 st.ownAttribute(texCoords0, true); 162 texCoords0.enableBuffer(gl, false); 163 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 164 165 final int texA0Point = 0; // attachment point for texA0 166 final int texA1Point = 1; // attachment point for texA1 167 168 // FBO w/ 2 texture2D color buffers 169 final FBObject fbo_mrt = new FBObject(); 170 fbo_mrt.init(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0); 171 final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); 172 final TextureAttachment texA1; 173 if(fbo_mrt.getMaxColorAttachments() > 1) { 174 texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); 175 } else { 176 texA1 = null; 177 System.err.println("FBO supports only one attachment, no MRT available!"); 178 } 179 fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, FBObject.CHOSEN_BITS); 180 Assert.assertTrue( fbo_mrt.isStatusValid() ) ; 181 fbo_mrt.unbind(gl); 182 183 // misc GL setup 184 gl.glClearColor(1, 1, 1, 1); 185 gl.glEnable(GL.GL_DEPTH_TEST); 186 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 187 188 // reshape 189 pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); 190 pmvMatrix.glLoadIdentity(); 191 pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f); 192 pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); 193 pmvMatrix.glLoadIdentity(); 194 st.uniform(gl, pmvMatrixUniform); 195 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); 196 197 final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0+texA0Point, GL.GL_COLOR_ATTACHMENT0+texA1Point }; 198 final int[] bck_buffers = new int[] { GL2GL3.GL_BACK_LEFT }; 199 200 final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); 201 int step_i = 0; 202 final int[] last_snap_size = new int[] { 0, 0 }; 203 204 for(int i=0; i<durationPerTest; i+=50) { 205 // pass 1 - MRT: Red -> buffer0, Green -> buffer1 206 st.attachShaderProgram(gl, sp0, true); 207 vertices0.enableBuffer(gl, true); 208 colors0.enableBuffer(gl, true); 209 210 fbo_mrt.bind(gl); 211 gl.glDrawBuffers(2, two_buffers, 0); 212 gl.glViewport(0, 0, fbo_mrt.getWidth(), fbo_mrt.getHeight()); 213 214 gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); 215 gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); 216 fbo_mrt.unbind(gl); 217 vertices0.enableBuffer(gl, false); 218 colors0.enableBuffer(gl, false); 219 220 // pass 2 - mix buffer0, buffer1 and blue 221 // rg = buffer0.rg + buffer1.rg, b = Blue - length(rg); 222 st.attachShaderProgram(gl, sp1, true); 223 vertices0.enableBuffer(gl, true); 224 colors0.enableBuffer(gl, true); 225 texCoords0.enableBuffer(gl, true); 226 gl.glDrawBuffers(1, bck_buffers, 0); 227 228 gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); 229 230 gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); 231 fbo_mrt.use(gl, texA0); 232 if(null != texA1) { 233 gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue()); 234 fbo_mrt.use(gl, texA1); 235 } 236 gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); 237 gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); 238 fbo_mrt.unuse(gl); 239 vertices0.enableBuffer(gl, false); 240 colors0.enableBuffer(gl, false); 241 texCoords0.enableBuffer(gl, false); 242 243 { 244 final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface(); 245 if(last_snap_size[0] != ns.getSurfaceWidth() && last_snap_size[1] != ns.getSurfaceHeight()) { 246 gl.glFinish(); // sync .. no swap buffers yet! 247 snapshot(step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok 248 last_snap_size[0] = ns.getSurfaceWidth(); 249 last_snap_size[1] = ns.getSurfaceHeight(); 250 } 251 } 252 253 drawable.swapBuffers(); 254 Thread.sleep(50); 255 final int j = (int) ( i / (durationPerTest/step) ) + 1; 256 if(j>step_i) { 257 final int w = width/step * j; 258 final int h = height/step * j; 259 System.err.println("resize: "+step_i+" -> "+j+" - "+w+"x"+h); 260 fbo_mrt.reset(gl, w, h, 0); 261 winctx.window.setSize(w, h); 262 step_i = j; 263 } 264 } 265 266 NEWTGLContext.destroyWindow(winctx); 267 } 268 main(final String args[])269 public static void main(final String args[]) throws IOException { 270 System.err.println("main - start"); 271 for(int i=0; i<args.length; i++) { 272 if(args[i].equals("-time")) { 273 durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); 274 } 275 } 276 final String tstname = TestFBOMRTNEWT01.class.getName(); 277 org.junit.runner.JUnitCore.main(tstname); 278 System.err.println("main - end"); 279 } 280 } 281 282