Jogamp
Add javadoc arg (property 'javadoc.xarg1') '-Xdoclint:none' if java >= 1.8 (GlueGen...
[jogl-demos.git] / src / demos / vertexArrayRange / VertexArrayRange.java
1 /*
2  * Portions Copyright (C) 2003 Sun Microsystems, Inc.
3  * All rights reserved.
4  */
5
6 /*
7  *
8  * COPYRIGHT NVIDIA CORPORATION 2003. ALL RIGHTS RESERVED.
9  * BY ACCESSING OR USING THIS SOFTWARE, YOU AGREE TO:
10  *
11  *  1) ACKNOWLEDGE NVIDIA'S EXCLUSIVE OWNERSHIP OF ALL RIGHTS
12  *     IN AND TO THE SOFTWARE;
13  *
14  *  2) NOT MAKE OR DISTRIBUTE COPIES OF THE SOFTWARE WITHOUT
15  *     INCLUDING THIS NOTICE AND AGREEMENT;
16  *
17  *  3) ACKNOWLEDGE THAT TO THE MAXIMUM EXTENT PERMITTED BY
18  *     APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS* AND
19  *     THAT NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES,
20  *     EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED
21  *     TO, IMPLIED WARRANTIES OF MERCHANTABILITY  AND FITNESS
22  *     FOR A PARTICULAR PURPOSE.
23  *
24  * IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY
25  * SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
26  * WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
27  * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
28  * INFORMATION, OR ANY OTHER PECUNIARY LOSS), INCLUDING ATTORNEYS'
29  * FEES, RELATING TO THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  *
32  */
33
34 package demos.vertexArrayRange;
35
36 import demos.common.Demo;
37 import demos.common.DemoListener;
38 import java.awt.BorderLayout;
39 import java.awt.Frame;
40 import java.awt.event.KeyAdapter;
41 import java.awt.event.KeyEvent;
42 import java.awt.event.WindowAdapter;
43 import java.awt.event.WindowEvent;
44 import java.nio.ByteBuffer;
45 import java.nio.ByteOrder;
46 import java.nio.FloatBuffer;
47 import java.nio.IntBuffer;
48 import com.jogamp.opengl.GL;
49 import com.jogamp.opengl.GL2ES1;
50 import com.jogamp.opengl.GL2;
51 import com.jogamp.opengl.GLAutoDrawable;
52 import com.jogamp.opengl.awt.GLCanvas;
53 import com.jogamp.opengl.glu.GLU;
54 import com.jogamp.opengl.util.Animator;
55 import javax.swing.JOptionPane;
56
57
58
59 /** <P> A port of NVidia's [tm] Vertex Array Range demonstration to
60     OpenGL[tm] for Java[tm] and the Java programming language. The
61     current web site for the demo (which does not appear to contain
62     the original C++ source code for this demo) is <a href =
63     "http://developer.nvidia.com/view.asp?IO=Using_GL_NV_fence">here</a>. </P>
64
65     <P> This demonstration requires the following:
66
67     <ul>
68     <li> A JDK 1.4 implementation
69     <li> an NVidia GeForce-based card
70     <li> a recent set of drivers
71     </ul>
72
73     </P>
74
75     <P> This demonstration illustrates the effective use of the
76     java.nio direct buffer classes in JDK 1.4 to access memory outside
77     of the Java garbage-collected heap, in particular that returned
78     from the NVidia-specific routine wglAllocateMemoryNV. This memory
79     region is used in conjunction with glVertexArrayRangeNV. </P>
80
81     <P> On a 750 MHz PIII with an SDRAM memory bus and a GeForce 256
82     running the Java HotSpot[tm] Client VM and OpenGL for Java 2.8,
83     this demonstration attains 90% of the speed of the compiled C++
84     code, with a frame rate of 27 FPS, compared to 30 FPS for the C++
85     version. On higher-end hardware (a dual 667 MHz PIII with RDRAM
86     and a GeForce 2) the demo currently attains between 65% and 75% of
87     C++ speed with the HotSpot Client and Server compilers,
88     respectively. </P> */
89
90 public class VertexArrayRange extends Demo {
91   public static void main(String[] args) {
92     boolean startSlow = false;
93
94     if (args.length > 1) {
95       usage();
96     }
97
98     if (args.length == 1) {
99       if (args[0].equals("-slow")) {
100         startSlow = true;
101       } else {
102         usage();
103       }
104     }
105
106     GLCanvas canvas = new GLCanvas();
107     VertexArrayRange demo = new VertexArrayRange();
108     if (startSlow) {
109       demo.setFlag('v', false);   // VAR off
110     }
111     canvas.addGLEventListener(demo);
112
113     final VertexArrayRange f_demo = demo;
114     canvas.addKeyListener(new KeyAdapter() {
115         public void keyTyped(KeyEvent e) {
116           f_demo.dispatchKey(e.getKeyChar());
117         }
118       });
119
120
121     final Animator animator = new Animator(canvas);
122     animator.setRunAsFastAsPossible(true);
123     demo.setDemoListener(new DemoListener() {
124         public void shutdownDemo() {
125           runExit(animator);
126         }
127         public void repaint() {}
128       });
129
130     Frame frame = new Frame("Very Simple NV_vertex_array_range demo");
131     frame.addWindowListener(new WindowAdapter() {
132         public void windowClosing(WindowEvent e) {
133           runExit(animator);
134         }
135       });
136     frame.setLayout(new BorderLayout());
137     canvas.setSize(800, 800);
138     frame.add(canvas, BorderLayout.CENTER);
139     frame.pack();
140     frame.setVisible(true);
141     canvas.requestFocus();
142
143     animator.start();
144   }
145
146   private static void usage() {
147     System.out.println("usage: java VertexArrayRange [-slow]");
148     System.out.println("-slow flag starts up using data in the Java heap");
149     System.exit(0);
150   }
151
152   public VertexArrayRange() {
153     setFlag(' ', true);   // animation on
154     setFlag('i', true);   // infinite viewer and light
155     setFlag('v', true);   // VAR on
156   }
157
158   //----------------------------------------------------------------------
159   // Internals only below this point
160   //
161
162   private GLU glu = new GLU();
163   private boolean[] b = new boolean[256];
164   private static final int SIZEOF_FLOAT = 4;
165   private static final int STRIP_SIZE  = 48;
166   private int tileSize   = 9 * STRIP_SIZE;
167   private int numBuffers = 4;
168   private int bufferLength = 1000000;
169   private int bufferSize   = bufferLength * SIZEOF_FLOAT;
170   private static final int SIN_ARRAY_SIZE = 1024;
171
172   private FloatBuffer bigArrayVar;
173   private FloatBuffer bigArraySystem;
174   private FloatBuffer bigArray;
175   private IntBuffer[] elements;
176   private float[]    xyArray;
177
178   static class VarBuffer {
179     public FloatBuffer vertices;
180     public FloatBuffer normals;
181     public int        fence;
182   }
183   private VarBuffer[] buffers;
184
185   private float[] sinArray;
186   private float[] cosArray;
187
188   // Primitive: GL_QUAD_STRIP, GL_LINE_STRIP, or GL_POINTS
189   private int primitive = GL2.GL_QUAD_STRIP;
190
191   // Animation parameters
192   private float hicoef = .06f;
193   private float locoef = .10f;
194   private float hifreq = 6.1f;
195   private float lofreq = 2.5f;
196   private float phaseRate = .02f;
197   private float phase2Rate = -0.12f;
198   private float phase  = 0;
199   private float phase2 = 0;
200
201   // Temporaries for computation
202   float[] ysinlo = new float[STRIP_SIZE];
203   float[] ycoslo = new float[STRIP_SIZE];
204   float[] ysinhi = new float[STRIP_SIZE];
205   float[] ycoshi = new float[STRIP_SIZE];
206
207   // For thread-safety when dealing with keypresses
208   private volatile boolean toggleVAR           = false;
209   private volatile boolean toggleLighting      = false;
210   private volatile boolean toggleLightingModel = false;
211   private volatile boolean recomputeElements   = false;
212
213   // Frames-per-second computation
214   private boolean firstProfiledFrame;
215   private int     profiledFrameCount;
216   private int     numDrawElementsCalls;
217   private long startTimeMillis;
218
219   static class PeriodicIterator {
220     public PeriodicIterator(int arraySize,
221                             float period,
222                             float initialOffset,
223                             float delta) {
224       float arrayDelta =  arraySize * (delta / period); // floating-point steps-per-increment
225       increment = (int)(arrayDelta * (1<<16));          // fixed-point steps-per-increment
226
227       float offset = arraySize * (initialOffset / period); // floating-point initial index
228       initOffset = (int)(offset * (1<<16));                // fixed-point initial index
229
230         arraySizeMask = 0;
231         int i = 20; // array should be reasonably sized...
232         while((arraySize & (1<<i)) == 0) {
233           i--;
234         }
235         arraySizeMask = (1<<i)-1;
236         index = initOffset;
237     }
238
239     public PeriodicIterator(PeriodicIterator arg) {
240       this.arraySizeMask = arg.arraySizeMask;
241       this.increment = arg.increment;
242       this.initOffset = arg.initOffset;
243       this.index = arg.index;
244     }
245
246     public int getIndex() {
247       return (index >> 16) & arraySizeMask;
248     }
249
250     public void incr() {
251       index += increment;
252     }
253
254     public void decr() {
255       index -= increment;
256     }
257
258     public void reset() {
259       index = initOffset;
260     }
261
262     private int arraySizeMask;
263     // fraction bits == 16
264     private int increment;
265     private int initOffset;
266     private int index;
267   }
268
269   private void setFlag(char key, boolean val) {
270     b[((int) key) & 0xFF] = val;
271   }
272
273   private boolean getFlag(char key) {
274     return b[((int) key) & 0xFF];
275   }
276
277   private void ensurePresent(GL gl, String function) {
278     if (!gl.isFunctionAvailable(function)) {
279       final String message = "OpenGL routine \"" + function + "\" not available";
280       new Thread(new Runnable() {
281           public void run() {
282             JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE);
283             shutdownDemo();
284           }
285         }).start();
286       throw new RuntimeException(message);
287     }
288   }
289
290   public void init(GLAutoDrawable drawable) {
291     //    drawable.setGL(new TraceGL(drawable.getGL(), System.err));
292     //    drawable.setGL(new DebugGL(drawable.getGL()));
293
294     GL2 gl = drawable.getGL().getGL2();
295
296     // Try and disable synch-to-retrace for fastest framerate
297     gl.setSwapInterval(0);
298
299     try {
300       ensurePresent(gl, "glVertexArrayRangeNV");
301       ensurePresent(gl, "glGenFencesNV");
302       ensurePresent(gl, "glSetFenceNV");
303       ensurePresent(gl, "glTestFenceNV");
304       ensurePresent(gl, "glFinishFenceNV");
305       ensurePresent(gl, "glAllocateMemoryNV");
306     } catch (RuntimeException e) {
307       shutdownDemo();
308       throw (e);
309     }      
310       
311     gl.glEnable(GL.GL_DEPTH_TEST);
312
313     gl.glClearColor(0, 0, 0, 0);
314
315     gl.glEnable(GL2ES1.GL_LIGHT0);
316     gl.glEnable(GL2ES1.GL_LIGHTING);
317     gl.glEnable(GL2ES1.GL_NORMALIZE);
318     gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL2ES1.GL_AMBIENT, new float[]  {.1f, .1f,    0, 1}, 0);
319     gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL2ES1.GL_DIFFUSE, new float[]  {.6f, .6f,  .1f, 1}, 0);
320     gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL2ES1.GL_SPECULAR, new float[] { 1,    1, .75f, 1}, 0);
321     gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL2ES1.GL_SHININESS, 128.f);
322
323     gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_POSITION, new float[] { .5f, 0, .5f, 0}, 0);
324     gl.glLightModeli(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
325
326     // NOTE: it looks like GLUT (or something else) sets up the
327     // projection matrix in the C version of this demo.
328     gl.glMatrixMode(GL2ES1.GL_PROJECTION);
329     gl.glLoadIdentity();
330     glu.gluPerspective(60, 1.0, 0.1, 100);
331     gl.glMatrixMode(GL2ES1.GL_MODELVIEW);
332
333     allocateBigArray(gl, true);
334     allocateBuffersAndFences(gl);
335
336     sinArray = new float[SIN_ARRAY_SIZE];
337     cosArray = new float[SIN_ARRAY_SIZE];
338
339     for (int i = 0; i < SIN_ARRAY_SIZE; i++) {
340       double step = i * 2 * Math.PI / SIN_ARRAY_SIZE;
341       sinArray[i] = (float) Math.sin(step);
342       cosArray[i] = (float) Math.cos(step);
343     }
344
345     if (getFlag('v')) {
346       gl.glEnableClientState(GL2.GL_VERTEX_ARRAY_RANGE_NV);
347       gl.glVertexArrayRangeNV(bufferSize, bigArrayVar);
348       bigArray = bigArrayVar;
349     } else {
350       bigArray = bigArraySystem;
351     }
352     setupBuffers();
353     gl.glEnableClientState(GL2ES1.GL_VERTEX_ARRAY);
354     gl.glEnableClientState(GL2ES1.GL_NORMAL_ARRAY);
355
356     computeElements();
357   }
358
359   private void allocateBuffersAndFences(GL2 gl) {
360     buffers = new VarBuffer[numBuffers];
361     int[] fences = new int[1];
362     for (int i = 0; i < numBuffers; i++) {
363       buffers[i] = new VarBuffer();
364       gl.glGenFencesNV(1, fences, 0);
365       buffers[i].fence = fences[0];
366     }
367   }
368
369   private void setupBuffers() {
370     int sliceSize = bufferLength / numBuffers;
371     for (int i = 0; i < numBuffers; i++) {
372       int startIndex = i * sliceSize;
373       buffers[i].vertices = sliceBuffer(bigArray, startIndex, sliceSize);
374       buffers[i].normals  = sliceBuffer(buffers[i].vertices, 3,
375                                         buffers[i].vertices.limit() - 3);
376     }
377   }
378
379   private void dispatchKey(char k) {
380     setFlag(k, !getFlag(k));
381     // Quit on escape or 'q'
382     if ((k == (char) 27) || (k == 'q')) {
383       shutdownDemo();
384       return;
385     }
386
387     if (k == 'r') {
388       if (getFlag(k)) {
389         profiledFrameCount = 0;
390         numDrawElementsCalls = 0;
391         firstProfiledFrame = true;
392       }
393     }
394
395     if (k == 'w') {
396       if (getFlag(k)) {
397         primitive = GL2.GL_LINE_STRIP;
398       } else {
399         primitive = GL2.GL_QUAD_STRIP;
400       }
401     }
402
403     if (k == 'p') {
404       if (getFlag(k)) {
405         primitive = GL2.GL_POINTS;
406       } else {
407         primitive = GL2.GL_QUAD_STRIP;
408       }
409     }
410
411     if (k == 'v') {
412       toggleVAR = true;
413     }
414
415     if (k == 'd') {
416       toggleLighting = true;
417     }
418
419     if (k == 'i') {
420       toggleLightingModel = true;
421     }
422
423     if('h'==k)
424       hicoef += .005;
425     if('H'==k)
426       hicoef -= .005;
427     if('l'==k)
428       locoef += .005;
429     if('L'==k)
430       locoef -= .005;
431     if('1'==k)
432       lofreq += .1f;
433     if('2'==k)
434       lofreq -= .1f;
435     if('3'==k)
436       hifreq += .1f;
437     if('4'==k)
438       hifreq -= .1f;
439     if('5'==k)
440       phaseRate += .01f;
441     if('6'==k)
442       phaseRate -= .01f;
443     if('7'==k)
444       phase2Rate += .01f;
445     if('8'==k)
446       phase2Rate -= .01f;
447
448     if('t'==k) {
449       if(tileSize < 864) {
450         tileSize += STRIP_SIZE;
451         recomputeElements = true;
452         System.err.println("tileSize = " + tileSize);
453       }
454     }
455
456     if('T'==k) {
457       if(tileSize > STRIP_SIZE) {
458         tileSize -= STRIP_SIZE;
459         recomputeElements = true;
460         System.err.println("tileSize = " + tileSize);
461       }
462     }
463   }
464
465   public void dispose(GLAutoDrawable drawable) {
466   }
467
468   public void display(GLAutoDrawable drawable) {
469     GL2 gl = drawable.getGL().getGL2();
470
471     // Check to see whether to animate
472     if (getFlag(' ')) {
473       phase += phaseRate;
474       phase2 += phase2Rate;
475
476       if (phase > (float) (20 * Math.PI)) {
477         phase = 0;
478       }
479
480       if (phase2 < (float) (-20 * Math.PI)) {
481         phase2 = 0;
482       }
483     }
484
485     PeriodicIterator loX =
486       new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase, (float) ((1.f/tileSize)*lofreq*Math.PI));
487     PeriodicIterator loY = new PeriodicIterator(loX);
488     PeriodicIterator hiX =
489       new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase2, (float) ((1.f/tileSize)*hifreq*Math.PI));
490     PeriodicIterator hiY = new PeriodicIterator(hiX);
491
492     if (toggleVAR) {
493       if (getFlag('v')) {
494         gl.glEnableClientState(GL2.GL_VERTEX_ARRAY_RANGE_NV);
495         gl.glVertexArrayRangeNV(bufferSize, bigArrayVar);
496         bigArray = bigArrayVar;
497       } else {
498         gl.glDisableClientState(GL2.GL_VERTEX_ARRAY_RANGE_NV);
499         bigArray = bigArraySystem;
500       }
501       toggleVAR = false;
502       setupBuffers();
503     }
504
505     if (toggleLighting) {
506       if (getFlag('d')) {
507         gl.glDisable(GL2ES1.GL_LIGHTING);
508       } else {
509         gl.glEnable(GL2ES1.GL_LIGHTING);
510       }
511       toggleLighting = false;
512     }
513
514     if (toggleLightingModel) {
515       if(getFlag('i')) {
516         // infinite light
517         gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_POSITION, new float[] { .5f, 0, .5f, 0 }, 0);
518         gl.glLightModeli(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
519       } else {
520         gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_POSITION, new float[] { .5f, 0, -.5f, 1 }, 0);
521         gl.glLightModeli(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
522       }
523       toggleLightingModel = false;
524     }
525
526     if (recomputeElements) {
527       computeElements();
528       recomputeElements = false;
529     }
530
531     gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
532
533     gl.glPushMatrix();
534
535     final float[] modelViewMatrix = new float[] {
536       1, 0, 0, 0,
537       0, 1, 0, 0,
538       0, 0, 1, 0,
539       0, 0, -1, 1
540     };
541     gl.glLoadMatrixf(modelViewMatrix, 0);
542
543     // FIXME: add mouse interaction
544     // camera.apply_inverse_transform();
545     // object.apply_transform();
546
547     int cur = 0;
548     int numSlabs = tileSize / STRIP_SIZE;
549
550     for(int slab = numSlabs; --slab>=0; ) {
551       cur = slab % numBuffers;
552       if (slab >= numBuffers) {
553         if (!gl.glTestFenceNV(buffers[cur].fence)) {
554           gl.glFinishFenceNV(buffers[cur].fence);
555         }
556       }
557
558       FloatBuffer v = buffers[cur].vertices;
559       int vertexIndex = 0;
560
561       gl.glVertexPointer(3, GL.GL_FLOAT, 6 * SIZEOF_FLOAT, v);
562       gl.glNormalPointer(GL.GL_FLOAT, 6 * SIZEOF_FLOAT, buffers[cur].normals);
563
564       for(int jj=STRIP_SIZE; --jj>=0; ) {
565         ysinlo[jj] = sinArray[loY.getIndex()];
566         ycoslo[jj] = cosArray[loY.getIndex()]; loY.incr();
567         ysinhi[jj] = sinArray[hiY.getIndex()];
568         ycoshi[jj] = cosArray[hiY.getIndex()]; hiY.incr();
569       }
570       loY.decr();
571       hiY.decr();
572
573       for(int i = tileSize; --i>=0; ) {
574         float x = xyArray[i];
575         int loXIndex = loX.getIndex();
576         int hiXIndex = hiX.getIndex();
577
578         int jOffset = (STRIP_SIZE-1)*slab;
579         float nx = locoef * -cosArray[loXIndex] + hicoef * -cosArray[hiXIndex];
580
581         // Help the HotSpot Client Compiler by hoisting loop
582         // invariant variables into locals. Note that this may be
583         // good practice for innermost loops anyway since under
584         // the new memory model operations like accidental
585         // synchronization may force any compiler to reload these
586         // fields from memory, destroying their ability to
587         // optimize.
588         float locoef_tmp = locoef;
589         float hicoef_tmp = hicoef;
590         float[] ysinlo_tmp = ysinlo;
591         float[] ysinhi_tmp = ysinhi;
592         float[] ycoslo_tmp = ycoslo;
593         float[] ycoshi_tmp = ycoshi;
594         float[] sinArray_tmp = sinArray;
595         float[] xyArray_tmp = xyArray;
596
597         for(int j = STRIP_SIZE; --j>=0; ) {
598           float y;
599
600           y = xyArray_tmp[j + jOffset];
601
602           float ny;
603
604           v.put(vertexIndex, x);
605           v.put(vertexIndex + 1, y);
606           v.put(vertexIndex + 2, (locoef_tmp * (sinArray_tmp[loXIndex] + ysinlo_tmp[j]) +
607                                   hicoef_tmp * (sinArray_tmp[hiXIndex] + ysinhi_tmp[j])));
608           v.put(vertexIndex + 3, nx);
609           ny = locoef_tmp * -ycoslo_tmp[j] + hicoef_tmp * -ycoshi_tmp[j];
610           v.put(vertexIndex + 4, ny);
611           v.put(vertexIndex + 5, .15f); //.15f * (1.f - sqrt(nx * nx + ny * ny));
612           vertexIndex += 6;
613         }
614         loX.incr();
615         hiX.incr();
616       }
617       loX.reset();
618       hiX.reset();
619
620       for (int i = 0; i < elements.length; i++) {
621         ++numDrawElementsCalls;
622         gl.glDrawElements(primitive, elements[i].capacity(), GL2.GL_UNSIGNED_INT, elements[i]);
623         if(getFlag('f')) {
624           gl.glFlush();
625         }
626       }
627
628       gl.glSetFenceNV(buffers[cur].fence, GL2.GL_ALL_COMPLETED_NV);
629     }
630
631     gl.glPopMatrix();
632
633     gl.glFinishFenceNV(buffers[cur].fence);
634
635     if (getFlag('r')) {
636       if (!firstProfiledFrame) {
637         if (++profiledFrameCount == 30) {
638           long endTimeMillis = System.currentTimeMillis();
639           double secs = (endTimeMillis - startTimeMillis) / 1000.0;
640           double fps  = 30.0 / secs;
641           double ppf  = tileSize * tileSize * 2;
642           double mpps = ppf * fps / 1000000.0;
643           System.err.println("fps: " + fps + " polys/frame: " + ppf + " million polys/sec: " + mpps +
644                              " DrawElements calls/frame: " + (numDrawElementsCalls / 30));
645           profiledFrameCount = 0;
646           numDrawElementsCalls = 0;
647           startTimeMillis = System.currentTimeMillis();
648         }
649       } else {
650         startTimeMillis = System.currentTimeMillis();
651         firstProfiledFrame = false;
652
653       }
654     }
655   }
656
657   public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
658
659   // Unused routines
660   public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
661
662   private void allocateBigArray(GL2 gl, boolean tryAgain) {
663     float priority = .5f;
664
665     bigArraySystem = setupBuffer(ByteBuffer.allocateDirect(bufferSize));
666
667     float megabytes = (bufferSize / 1000000.f);
668     try {
669       bigArrayVar = setupBuffer(gl.glAllocateMemoryNV(bufferSize, 0, 0, priority));
670     }
671     catch (OutOfMemoryError e1) {
672       // Try a higher priority
673       try {
674         bigArrayVar = setupBuffer(gl.glAllocateMemoryNV(bufferSize, 0, 0, 1.f));
675       }
676       catch (OutOfMemoryError e2) {
677         if (!tryAgain) {
678           throw new RuntimeException("Unable to allocate " + megabytes +
679                                      " megabytes of fast memory. Giving up.");
680         }
681
682         System.err.println("Unable to allocate " + megabytes +
683                            " megabytes of fast memory. Trying less.");
684         bufferSize /= 2;
685         numBuffers /= 2;
686         allocateBigArray(gl, false);
687         return;
688       }
689     }
690
691     System.err.println("Allocated " + megabytes + " megabytes of fast memory");
692   }
693
694   private FloatBuffer setupBuffer(ByteBuffer buf) {
695     buf.order(ByteOrder.nativeOrder());
696     return buf.asFloatBuffer();
697   }
698
699   private FloatBuffer sliceBuffer(FloatBuffer array,
700                                   int sliceStartIndex, int sliceLength) {
701     array.position(sliceStartIndex);
702     FloatBuffer ret = array.slice();
703     array.position(0);
704     ret.limit(sliceLength);
705     return ret;
706   }
707
708   private void computeElements() {
709     xyArray = new float[tileSize];
710     for (int i = 0; i < tileSize; i++) {
711       xyArray[i] = i / (tileSize - 1.0f) - 0.5f;
712     }
713
714     elements = new IntBuffer[tileSize - 1];
715     for (int i = 0; i < tileSize - 1; i++) {
716       elements[i] = IntBuffer.allocate(2 * STRIP_SIZE);
717       for (int j = 0; j < 2 * STRIP_SIZE; j += 2) {
718         elements[i].put(j,    i      * STRIP_SIZE + (j / 2));
719         elements[i].put(j+1, (i + 1) * STRIP_SIZE + (j / 2));
720       }
721     }
722   }
723
724   private static void runExit(final Animator animator) {
725     // Note: calling System.exit() synchronously inside the draw,
726     // reshape or init callbacks can lead to deadlocks on certain
727     // platforms (in particular, X11) because the JAWT's locking
728     // routines cause a global AWT lock to be grabbed. Run the
729     // exit routine in another thread.
730     new Thread(new Runnable() {
731         public void run() {
732           animator.stop();
733           System.exit(0);
734         }
735       }).start();
736   }
737 }
http://JogAmp.org git info: FAQ, tutorial and man pages.