Jogamp
Bug 741 HiDPI: Add ScalableSurface interface to get/set pixelScale w/ full OSX impl.
[jogl.git] / src / test / com / jogamp / opengl / test / junit / jogl / demos / es2 / awt / TestGearsES2AWT.java
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
29 package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
30
31 import javax.media.nativewindow.ScalableSurface;
32 import javax.media.opengl.*;
33
34 import com.jogamp.opengl.util.Animator;
35
36 import javax.media.opengl.awt.GLCanvas;
37
38 import com.jogamp.common.os.Platform;
39 import com.jogamp.newt.event.awt.AWTKeyAdapter;
40 import com.jogamp.newt.event.awt.AWTWindowAdapter;
41 import com.jogamp.newt.event.KeyEvent;
42 import com.jogamp.newt.event.TraceKeyAdapter;
43 import com.jogamp.newt.event.TraceWindowAdapter;
44 import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
45 import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
46 import com.jogamp.opengl.test.junit.util.MiscUtils;
47 import com.jogamp.opengl.test.junit.util.UITestCase;
48 import com.jogamp.opengl.test.junit.util.QuitAdapter;
49
50 import java.awt.BorderLayout;
51 import java.awt.Button;
52 import java.awt.Component;
53 import java.awt.Container;
54 import java.awt.Dimension;
55 import java.awt.EventQueue;
56 import java.awt.Frame;
57 import java.awt.TextArea;
58 import java.awt.event.ComponentEvent;
59 import java.awt.event.ComponentListener;
60 import java.io.BufferedReader;
61 import java.io.IOException;
62 import java.io.InputStreamReader;
63 import java.lang.reflect.InvocationTargetException;
64
65 import org.junit.Assert;
66 import org.junit.Assume;
67 import org.junit.BeforeClass;
68 import org.junit.AfterClass;
69 import org.junit.Test;
70 import org.junit.FixMethodOrder;
71 import org.junit.runners.MethodSorters;
72
73 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
74 public class TestGearsES2AWT extends UITestCase {
75     public enum FrameLayout { None, TextOnBottom, BorderCenterSurrounded, DoubleBorderCenterSurrounded };
76     public enum ResizeBy { Component, Frame };
77
78     static long duration = 500; // ms
79     static int width = 640, height = 480;
80     static int xpos = 10, ypos = 10;
81     static FrameLayout frameLayout = FrameLayout.None;
82     static ResizeBy resizeBy = ResizeBy.Component;
83     static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
84
85     static boolean forceES2 = false;
86     static boolean forceGL3 = false;
87     static boolean mainRun = false;
88     static boolean shallUseOffscreenFBOLayer = false;
89     static boolean shallUseOffscreenPBufferLayer = false;
90     static boolean useMSAA = false;
91     static boolean useStencil = false;
92     static boolean shutdownRemoveGLCanvas = true;
93     static boolean shutdownDisposeFrame = true;
94     static boolean shutdownSystemExit = false;
95     static int swapInterval = 1;
96     static boolean exclusiveContext = false;
97     static boolean useAnimator = true;
98     static Thread awtEDT;
99     static java.awt.Dimension rwsize = null;
100
101     @BeforeClass
102     public static void initClass() {
103         try {
104             EventQueue.invokeAndWait(new Runnable() {
105                 public void run() {
106                     awtEDT = Thread.currentThread();
107                 } } );
108         } catch (Exception e) {
109             e.printStackTrace();
110             Assert.assertNull(e);
111         }
112     }
113
114     @AfterClass
115     public static void releaseClass() {
116     }
117
118     static void setComponentSize(final Frame frame, final Component comp, final java.awt.Dimension new_sz) {
119         try {
120             javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
121                 public void run() {
122                     comp.setMinimumSize(new_sz);
123                     comp.setPreferredSize(new_sz);
124                     comp.setSize(new_sz);
125                     if( null != frame ) {
126                         frame.pack();
127                     }
128                 } } );
129         } catch( Throwable throwable ) {
130             throwable.printStackTrace();
131             Assume.assumeNoException( throwable );
132         }
133     }
134     static void setFrameSize(final Frame frame, final boolean frameLayout, final java.awt.Dimension new_sz) {
135         try {
136             javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
137                 public void run() {
138                     frame.setSize(new_sz);
139                     if( frameLayout ) {
140                         frame.validate();
141                     }
142                 } } );
143         } catch( Throwable throwable ) {
144             throwable.printStackTrace();
145             Assume.assumeNoException( throwable );
146         }
147     }
148
149     static void setSize(final ResizeBy resizeBy, final Frame frame, final boolean frameLayout, final Component comp, final java.awt.Dimension new_sz) {
150         switch( resizeBy ) {
151             case Component:
152                 setComponentSize(frameLayout ? frame : null, comp, new_sz);
153                 break;
154             case Frame:
155                 setFrameSize(frame, frameLayout, new_sz);
156                 break;
157         }
158     }
159
160     private void setTitle(final Frame frame, final GLCanvas glc, final GLCapabilitiesImmutable caps) {
161         final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
162         final java.awt.Rectangle b = glc.getBounds();
163         frame.setTitle("GLCanvas["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight());
164     }
165
166     protected void runTestGL(final GLCapabilities caps, final ResizeBy resizeBy, FrameLayout frameLayout) throws InterruptedException, InvocationTargetException {
167         final Frame frame = new Frame("GearsES2 AWT Test");
168         Assert.assertNotNull(frame);
169
170         final GLCanvas glCanvas = new GLCanvas(caps);
171         Assert.assertNotNull(glCanvas);
172         setSize(resizeBy, frame, false, glCanvas, new Dimension(width, height));
173         glCanvas.setSurfaceScale(reqSurfacePixelScale);
174         frame.setLocation(xpos, ypos);
175
176         switch( frameLayout) {
177             case None:
178                 frame.add(glCanvas);
179                 break;
180             case TextOnBottom:
181                 final TextArea ta = new TextArea(2, 20);
182                 ta.append("0123456789");
183                 ta.append(Platform.getNewline());
184                 ta.append("Some Text");
185                 ta.append(Platform.getNewline());
186                 frame.setLayout(new BorderLayout());
187                 frame.add(ta, BorderLayout.SOUTH);
188                 frame.add(glCanvas, BorderLayout.CENTER);
189                 break;
190             case BorderCenterSurrounded:
191                 frame.setLayout(new BorderLayout());
192                 frame.add(new Button("NORTH"), BorderLayout.NORTH);
193                 frame.add(new Button("SOUTH"), BorderLayout.SOUTH);
194                 frame.add(new Button("EAST"), BorderLayout.EAST);
195                 frame.add(new Button("WEST"), BorderLayout.WEST);
196                 frame.add(glCanvas, BorderLayout.CENTER);
197                 break;
198             case DoubleBorderCenterSurrounded:
199                 Container c = new Container();
200                 c.setLayout(new BorderLayout());
201                 c.add(new Button("north"), BorderLayout.NORTH);
202                 c.add(new Button("south"), BorderLayout.SOUTH);
203                 c.add(new Button("east"), BorderLayout.EAST);
204                 c.add(new Button("west"), BorderLayout.WEST);
205                 c.add(glCanvas, BorderLayout.CENTER);
206
207                 frame.setLayout(new BorderLayout());
208                 frame.add(new Button("NORTH"), BorderLayout.NORTH);
209                 frame.add(new Button("SOUTH"), BorderLayout.SOUTH);
210                 frame.add(new Button("EAST"), BorderLayout.EAST);
211                 frame.add(new Button("WEST"), BorderLayout.WEST);
212                 frame.add(c, BorderLayout.CENTER);
213                 break;
214         }
215         setTitle(frame, glCanvas, caps);
216
217         frame.addComponentListener(new ComponentListener() {
218             @Override
219             public void componentResized(ComponentEvent e) {
220                 setTitle(frame, glCanvas, caps);
221             }
222
223             @Override
224             public void componentMoved(ComponentEvent e) {
225                 setTitle(frame, glCanvas, caps);
226             }
227
228             @Override
229             public void componentShown(ComponentEvent e) { }
230
231             @Override
232             public void componentHidden(ComponentEvent e) { }
233         });
234
235         final GearsES2 demo = new GearsES2(swapInterval);
236         glCanvas.addGLEventListener(demo);
237
238         final SnapshotGLEventListener snap = new SnapshotGLEventListener();
239         glCanvas.addGLEventListener(snap);
240
241         final Animator animator = useAnimator ? new Animator(glCanvas) : null;
242         if( useAnimator && exclusiveContext ) {
243             animator.setExclusiveContext(awtEDT);
244         }
245         final QuitAdapter quitAdapter = new QuitAdapter();
246         new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glCanvas).addTo(glCanvas);
247         new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas).addTo(frame);
248
249         final com.jogamp.newt.event.KeyListener kl = new com.jogamp.newt.event.KeyAdapter() {
250             @Override
251             public void keyPressed(final KeyEvent e) {
252                 if( e.isAutoRepeat() ) {
253                     return;
254                 }
255                 if(e.getKeyChar()=='x') {
256                     final int[] hadSurfacePixelScale = glCanvas.getSurfaceScale(new int[2]);
257                     final int[] reqSurfacePixelScale;
258                     if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
259                         reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
260                     } else {
261                         reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
262                     }
263                     System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
264                     glCanvas.setSurfaceScale(reqSurfacePixelScale);
265                     final int[] hasSurfacePixelScale0 = glCanvas.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
266                     final int[] hasSurfacePixelScale1 = glCanvas.getSurfaceScale(new int[2]);
267                     System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
268                                        reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
269                                        hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
270                     setTitle(frame, glCanvas, caps);
271                     Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
272                 }
273             } };
274         new AWTKeyAdapter(kl, glCanvas).addTo(glCanvas);
275
276         javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
277             public void run() {
278                if( ResizeBy.Frame == resizeBy ) {
279                    frame.validate();
280                } else {
281                    frame.pack();
282                }
283                frame.setVisible(true);
284             }});
285         Assert.assertEquals(true,  AWTRobotUtil.waitForVisible(frame, true));
286         Assert.assertEquals(true,  AWTRobotUtil.waitForRealized(glCanvas, true));
287
288         final int[] hasSurfacePixelScale0 = glCanvas.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
289         final int[] hasSurfacePixelScale1 = glCanvas.getSurfaceScale(new int[2]);
290         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
291                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
292         setTitle(frame, glCanvas, caps);
293         Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
294
295         if( useAnimator ) {
296             animator.start();
297             Assert.assertTrue(animator.isStarted());
298             Assert.assertTrue(animator.isAnimating());
299             Assert.assertEquals(exclusiveContext ? awtEDT : null, glCanvas.getExclusiveContextThread());
300             animator.setUpdateFPSFrames(60, System.err);
301         }
302
303         System.err.println("canvas pos/siz: "+glCanvas.getX()+"/"+glCanvas.getY()+" "+glCanvas.getSurfaceWidth()+"x"+glCanvas.getSurfaceHeight());
304
305         snap.setMakeSnapshot();
306
307         if( null != rwsize ) {
308             Thread.sleep(500); // 500ms delay
309             setSize(resizeBy, frame, true, glCanvas, rwsize);
310             System.err.println("window resize pos/siz: "+glCanvas.getX()+"/"+glCanvas.getY()+" "+glCanvas.getSurfaceWidth()+"x"+glCanvas.getSurfaceHeight());
311         }
312
313         snap.setMakeSnapshot();
314
315         final long t0 = System.currentTimeMillis();
316         long t1 = t0;
317         while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
318             Thread.sleep(100);
319             t1 = System.currentTimeMillis();
320         }
321
322         Assert.assertNotNull(frame);
323         Assert.assertNotNull(glCanvas);
324
325         if( useAnimator ) {
326             Assert.assertNotNull(animator);
327             Assert.assertEquals(exclusiveContext ? awtEDT : null, glCanvas.getExclusiveContextThread());
328             animator.stop();
329             Assert.assertFalse(animator.isAnimating());
330             Assert.assertFalse(animator.isStarted());
331             Assert.assertEquals(null, glCanvas.getExclusiveContextThread());
332         }
333
334         javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
335             public void run() {
336                 frame.setVisible(false);
337             }});
338         Assert.assertEquals(false, frame.isVisible());
339         javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
340             public void run() {
341                 if(shutdownRemoveGLCanvas) {
342                     frame.remove(glCanvas);
343                 }
344                 if(shutdownDisposeFrame) {
345                     frame.dispose();
346                 }
347                 if(shutdownSystemExit) {
348                     System.exit(0);
349                 }
350             }});
351     }
352
353     @Test
354     public void test01() throws InterruptedException, InvocationTargetException {
355         final GLProfile glp;
356         if(forceGL3) {
357             glp = GLProfile.get(GLProfile.GL3);
358         } else if(forceES2) {
359             glp = GLProfile.get(GLProfile.GLES2);
360         } else {
361             glp = GLProfile.getGL2ES2();
362         }
363         final GLCapabilities caps = new GLCapabilities(glp);
364         if(useMSAA) {
365             caps.setNumSamples(4);
366             caps.setSampleBuffers(true);
367         }
368         if(useStencil) {
369             caps.setStencilBits(1);
370         }
371         if(shallUseOffscreenFBOLayer) {
372             caps.setOnscreen(false);
373         }
374         if(shallUseOffscreenPBufferLayer) {
375             caps.setPBuffer(true);
376         }
377         runTestGL(caps, resizeBy, frameLayout);
378     }
379
380     @Test
381     public void test02_GLES2() throws InterruptedException, InvocationTargetException {
382         if(mainRun) return;
383
384         if( !GLProfile.isAvailable(GLProfile.GLES2) ) {
385             System.err.println("GLES2 n/a");
386             return;
387         }
388         final GLProfile glp = GLProfile.get(GLProfile.GLES2);
389         final GLCapabilities caps = new GLCapabilities( glp );
390         runTestGL(caps, resizeBy, frameLayout);
391     }
392
393     @Test
394     public void test03_GL3() throws InterruptedException, InvocationTargetException {
395         if(mainRun) return;
396
397         if( !GLProfile.isAvailable(GLProfile.GL3) ) {
398             System.err.println("GL3 n/a");
399             return;
400         }
401         final GLProfile glp = GLProfile.get(GLProfile.GL3);
402         final GLCapabilities caps = new GLCapabilities( glp );
403         runTestGL(caps, resizeBy, frameLayout);
404     }
405
406     @Test
407     public void test99_PixelScale1_DefaultNorm() throws InterruptedException, InvocationTargetException {
408         if( mainRun ) return;
409
410         reqSurfacePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
411         reqSurfacePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
412
413         GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
414         runTestGL(caps, resizeBy, frameLayout);
415     }
416
417     public static void main(String args[]) {
418         boolean waitForKey = false;
419         int rw=-1, rh=-1;
420
421         mainRun = true;
422         for(int i=0; i<args.length; i++) {
423             if(args[i].equals("-time")) {
424                 i++;
425                 duration = MiscUtils.atol(args[i], duration);
426             } else if(args[i].equals("-width")) {
427                 i++;
428                 width = MiscUtils.atoi(args[i], width);
429             } else if(args[i].equals("-height")) {
430                 i++;
431                 height = MiscUtils.atoi(args[i], height);
432             } else if(args[i].equals("-x")) {
433                 i++;
434                 xpos = MiscUtils.atoi(args[i], xpos);
435             } else if(args[i].equals("-y")) {
436                 i++;
437                 ypos = MiscUtils.atoi(args[i], ypos);
438             } else if(args[i].equals("-rwidth")) {
439                 i++;
440                 rw = MiscUtils.atoi(args[i], rw);
441             } else if(args[i].equals("-rheight")) {
442                 i++;
443                 rh = MiscUtils.atoi(args[i], rh);
444             } else if(args[i].equals("-pixelScale")) {
445                 i++;
446                 final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
447                 reqSurfacePixelScale[0] = pS;
448                 reqSurfacePixelScale[1] = pS;
449             } else if(args[i].equals("-layout")) {
450                 i++;
451                 frameLayout = FrameLayout.valueOf(args[i]);
452             } else if(args[i].equals("-resizeBy")) {
453                 i++;
454                 resizeBy = ResizeBy.valueOf(args[i]);
455             } else if(args[i].equals("-es2")) {
456                 forceES2 = true;
457             } else if(args[i].equals("-gl3")) {
458                 forceGL3 = true;
459             } else if(args[i].equals("-vsync")) {
460                 i++;
461                 swapInterval = MiscUtils.atoi(args[i], swapInterval);
462             } else if(args[i].equals("-exclctx")) {
463                 exclusiveContext = true;
464             } else if(args[i].equals("-noanim")) {
465                 useAnimator  = false;
466             } else if(args[i].equals("-layeredFBO")) {
467                 shallUseOffscreenFBOLayer = true;
468             } else if(args[i].equals("-layeredPBuffer")) {
469                 shallUseOffscreenPBufferLayer = true;
470             } else if(args[i].equals("-msaa")) {
471                 useMSAA = true;
472             } else if(args[i].equals("-stencil")) {
473                 useStencil = true;
474             } else if(args[i].equals("-wait")) {
475                 waitForKey = true;
476             } else if(args[i].equals("-shutdownKeepGLCanvas")) {
477                 shutdownRemoveGLCanvas = false;
478             } else if(args[i].equals("-shutdownKeepFrame")) {
479                 shutdownDisposeFrame = false;
480             } else if(args[i].equals("-shutdownKeepAll")) {
481                 shutdownRemoveGLCanvas = false;
482                 shutdownDisposeFrame = false;
483             } else if(args[i].equals("-shutdownSystemExit")) {
484                 shutdownSystemExit = true;
485             }
486         }
487         if( 0 < rw && 0 < rh ) {
488             rwsize = new Dimension(rw, rh);
489         }
490
491         System.err.println("resize "+rwsize);
492         System.err.println("frameLayout "+frameLayout);
493         System.err.println("resizeBy "+resizeBy);
494         System.err.println("forceES2 "+forceES2);
495         System.err.println("forceGL3 "+forceGL3);
496         System.err.println("swapInterval "+swapInterval);
497         System.err.println("exclusiveContext "+exclusiveContext);
498         System.err.println("useMSAA "+useMSAA);
499         System.err.println("useAnimator "+useAnimator);
500
501         System.err.println("shallUseOffscreenFBOLayer     "+shallUseOffscreenFBOLayer);
502         System.err.println("shallUseOffscreenPBufferLayer "+shallUseOffscreenPBufferLayer);
503
504         if(waitForKey) {
505             BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
506             System.err.println("Press enter to continue");
507             try {
508                 System.err.println(stdin.readLine());
509             } catch (IOException e) { }
510         }
511         org.junit.runner.JUnitCore.main(TestGearsES2AWT.class.getName());
512     }
513 }
http://JogAmp.org git info: FAQ, tutorial and man pages.