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