Jogamp
Fix NEWT GLWindow: Adding missing shared GLContext setter (with unit test)
[jogl.git] / src / newt / classes / com / jogamp / newt / opengl / GLWindow.java
1 /*
2  * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
3  * Copyright (c) 2010 JogAmp Community. All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  * 
9  * - Redistribution of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  * 
12  * - Redistribution in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * 
16  * Neither the name of Sun Microsystems, Inc. or the names of
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  * 
20  * This software is provided "AS IS," without a warranty of any kind. ALL
21  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24  * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27  * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28  * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29  * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30  * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31  * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32  * 
33  */
34
35 package com.jogamp.newt.opengl;
36
37 import com.jogamp.common.GlueGenVersion;
38 import com.jogamp.common.util.VersionUtil;
39 import com.jogamp.nativewindow.NativeWindowVersion;
40 import com.jogamp.newt.*;
41 import com.jogamp.newt.event.*;
42 import com.jogamp.newt.impl.WindowImpl;
43 import javax.media.nativewindow.*;
44 import javax.media.nativewindow.util.Point;
45 import javax.media.opengl.*;
46 import com.jogamp.opengl.impl.GLDrawableHelper;
47 import com.jogamp.opengl.JoglVersion;
48 import javax.media.nativewindow.util.Insets;
49
50 /**
51  * An implementation of {@link javax.media.opengl.GLAutoDrawable} interface,
52  * using an aggregation of a {@link com.jogamp.newt.Window} implementation.
53  * <P>
54  * This implementation does not make the OpenGL context current<br>
55  * before calling the various input EventListener callbacks, ie {@link com.jogamp.newt.event.MouseListener} etc.<br>
56  * This design decision is made in favor of a more performant and simplified
57  * implementation. Also the event dispatcher shall be implemented OpenGL agnostic.<br>
58  * To be able to use OpenGL commands from within such input {@link com.jogamp.newt.event.NEWTEventListener},<br>
59  * you can inject {@link javax.media.opengl.GLRunnable} objects
60  * via {@link #invoke(boolean, javax.media.opengl.GLRunnable)} to the OpenGL command stream.<br>
61  * <p>
62  */
63 public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer {
64     private WindowImpl window;
65
66     /**
67      * Constructor. Do not call this directly -- use {@link #create()} instead.
68      */
69     protected GLWindow(Window window) {
70         resetCounter();
71         this.window = (WindowImpl) window;
72         ((WindowImpl)this.window).setHandleDestroyNotify(false);
73         window.addWindowListener(new WindowAdapter() {
74                 public void windowRepaint(WindowUpdateEvent e) {
75                     if( !GLWindow.this.window.isSurfaceLockedByOtherThread() && !GLWindow.this.helper.isExternalAnimatorAnimating() ) {
76                         display();
77                     }
78                 }
79
80                 public void windowResized(WindowEvent e) {
81                     sendReshape = true;
82                     if( !GLWindow.this.window.isSurfaceLockedByOtherThread() && !GLWindow.this.helper.isExternalAnimatorAnimating() ) {
83                         display();
84                     }
85                 }
86
87                 public void windowDestroyNotify(WindowEvent e) {
88                     // Is an animator thread perform rendering?
89                     if (GLWindow.this.helper.isExternalAnimatorRunning()) {
90                         // Pause animations before initiating safe destroy.
91                         GLAnimatorControl ctrl = GLWindow.this.helper.getAnimator();
92                         boolean isPaused = ctrl.pause();
93                         destroy();
94                         if(isPaused) {
95                             ctrl.resume();
96                         }
97                     } else if (GLWindow.this.window.isSurfaceLockedByOtherThread()) {
98                         // Surface is locked by another thread
99                         // Flag that destroy should be performed on the next
100                         // attempt to display.
101                         sendDestroy = true;
102                     } else {
103                         // Without an external thread animating or locking the
104                         // surface, we are safe.
105                         destroy ();
106                     }
107                 }
108             });
109         this.window.setLifecycleHook(new GLLifecycleHook());
110     }
111
112     /**
113      * Creates a new GLWindow attaching a new Window referencing a new Screen
114      * with the given GLCapabilities.
115      * <P>
116      * The resulting GLWindow owns the Window, Screen and Device, ie it will be destructed.
117      */
118     public static GLWindow create(GLCapabilitiesImmutable caps) {
119         return new GLWindow(NewtFactory.createWindow(caps));
120     }
121
122     /**
123      * Creates a new GLWindow attaching a new Window referencing the given Screen
124      * with the given GLCapabilities.
125      * <P>
126      * The resulting GLWindow owns the Window, ie it will be destructed.
127      */
128     public static GLWindow create(Screen screen, GLCapabilitiesImmutable caps) {
129         return new GLWindow(NewtFactory.createWindow(screen, caps));
130     }
131
132     /** 
133      * Creates a new GLWindow attaching the given window.
134      * <P>
135      * The resulting GLWindow does not own the given Window, ie it will not be destructed. 
136      */
137     public static GLWindow create(Window window) {
138         return new GLWindow(window);
139     }
140
141     /** 
142      * Creates a new GLWindow attaching a new child Window 
143      * of the given <code>parentNativeWindow</code> with the given GLCapabilities.
144      * <P>
145      * The Display/Screen will be compatible with the <code>parentNativeWindow</code>,
146      * or even identical in case it's a Newt Window.
147      * <P>
148      * The resulting GLWindow owns the Window, ie it will be destructed. 
149      */
150     public static GLWindow create(NativeWindow parentNativeWindow, GLCapabilitiesImmutable caps) {
151         return new GLWindow(NewtFactory.createWindow(parentNativeWindow, caps));
152     }
153
154     //----------------------------------------------------------------------
155     // Window Access
156     //
157
158     public CapabilitiesChooser setCapabilitiesChooser(CapabilitiesChooser chooser) {
159         return window.setCapabilitiesChooser(chooser);
160     }
161
162     public final CapabilitiesImmutable getChosenCapabilities() {
163         if (drawable == null) {
164             return window.getChosenCapabilities();
165         }
166
167         return drawable.getChosenGLCapabilities();
168     }
169
170     public final CapabilitiesImmutable getRequestedCapabilities() {
171         return window.getRequestedCapabilities();
172     }
173
174     public final Window getWindow() {
175         return window;
176     }
177
178     public final NativeWindow getParent() {
179         return window.getParent();
180     }
181
182     public final Screen getScreen() {
183         return window.getScreen();
184     }
185
186     public final void setTitle(String title) {
187         window.setTitle(title);
188     }
189
190     public final String getTitle() {
191         return window.getTitle();
192     }
193
194     public final void setUndecorated(boolean value) {
195         window.setUndecorated(value);
196     }
197
198     public final boolean isUndecorated() {
199         return window.isUndecorated();
200     }
201
202     public final void setFocusAction(FocusRunnable focusAction) {
203         window.setFocusAction(focusAction);
204     }
205     
206     public final void requestFocus() {
207         window.requestFocus();
208     }
209
210     public boolean hasFocus() {
211         return window.hasFocus();
212     }
213
214     public final Insets getInsets() {
215         return window.getInsets();
216     }
217
218     public final void setPosition(int x, int y) {
219         window.setPosition(x, y);
220     }
221
222     public final boolean setFullscreen(boolean fullscreen) {
223         return window.setFullscreen(fullscreen);
224     }
225
226     public final boolean isFullscreen() {
227         return window.isFullscreen();
228     }
229
230     public final boolean isVisible() {
231         return window.isVisible();
232     }
233
234     public final String toString() {
235         return "NEWT-GLWindow[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + 
236                ", \n\tContext: " + context + /** ", \n\tWindow: "+window+", \n\tFactory: "+factory+ */ "]";
237     }
238
239     public final int reparentWindow(NativeWindow newParent) {
240         return window.reparentWindow(newParent);
241     }
242
243     public final int reparentWindow(NativeWindow newParent, boolean forceDestroyCreate) {
244         return window.reparentWindow(newParent, forceDestroyCreate);
245     }
246
247     public final void removeChild(NativeWindow win) {
248         window.removeChild(win);
249     }
250
251     public final void addChild(NativeWindow win) {
252         window.addChild(win);
253     }
254     
255     //----------------------------------------------------------------------
256     // Window.LifecycleHook Implementation
257     //
258
259     public final void destroy() {
260         window.destroy();
261     }
262
263     public final void setVisible(boolean visible) {
264         window.setVisible(visible);
265     }
266
267     public final void setSize(int width, int height) {
268         window.setSize(width, height);
269     }
270
271     public final boolean isValid() {
272         return window.isValid();
273     }
274
275     public final boolean isNativeValid() {
276         return window.isNativeValid();
277     }
278
279     public Point getLocationOnScreen(Point storage) {
280         return window.getLocationOnScreen(storage);
281     }
282
283     // Hide methods here ..
284     protected class GLLifecycleHook implements WindowImpl.LifecycleHook {
285
286         class DisposeAction implements Runnable {
287             public void run() {
288                 // Lock: Covered by DestroyAction ..
289                 helper.dispose(GLWindow.this);
290             }
291         }
292         DisposeAction disposeAction = new DisposeAction();
293
294         public synchronized void destroyActionPreLock() {
295             // nop
296         }
297
298         public synchronized void destroyActionInLock() {
299             if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
300                 String msg = new String("GLWindow.destroy() "+Thread.currentThread()+", start");
301                 System.err.println(msg);
302                 //Exception e1 = new Exception(msg);
303                 //e1.printStackTrace();
304             }
305
306             if( window.isNativeValid() && null != drawable && drawable.isRealized() ) {
307                 if( null != context && context.isCreated() ) {
308                     // Catch dispose GLExceptions by GLEventListener, just 'print' them
309                     // so we can continue with the destruction.
310                     try {
311                         helper.invokeGL(drawable, context, disposeAction, null);
312                     } catch (GLException gle) {
313                         gle.printStackTrace();
314                     }
315                     context.destroy();
316                 }
317                 drawable.setRealized(false);
318             }
319             context = null;
320             drawable = null;
321
322             if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
323                 System.err.println("GLWindow.destroy() "+Thread.currentThread()+", fin");
324             }
325         }
326
327         public synchronized void invalidate(boolean unrecoverable) {
328             if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
329                 String msg = new String("GLWindow.invalidate("+unrecoverable+") "+Thread.currentThread()+", start");
330                 System.err.println(msg);
331                 //Exception e1 = new Exception(msg);
332                 //e1.printStackTrace();
333             }
334             if(unrecoverable) {
335                 GLAnimatorControl ctrl = GLWindow.this.getAnimator();
336                 if ( null!=ctrl ) {
337                     ctrl.remove(GLWindow.this);
338                 }
339                 helper=null;
340             }
341         }
342
343         public synchronized void resetCounter() {
344             if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
345                 System.err.println("GLWindow.resetCounter() "+Thread.currentThread());
346             }
347             GLWindow.this.resetCounter();
348         }
349
350         public synchronized void setVisibleActionPost(boolean visible, boolean nativeWindowCreated) {
351             if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
352                 String msg = new String("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+Thread.currentThread()+", start");
353                 System.err.println(msg);
354                 // Exception e1 = new Exception(msg);
355                 // e1.printStackTrace();
356             }
357
358             /* if (nativeWindowCreated && null != context) {
359                 throw new GLException("InternalError: Native Windows has been just created, but context wasn't destroyed (is not null)");
360             } */
361             if (null == context && visible && 0 != window.getWindowHandle() && 0<getWidth()*getHeight()) {
362                 NativeWindow nw;
363                 if (window.getWrappedWindow() != null) {
364                     nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration());
365                 } else {
366                     nw = window;
367                 }
368                 GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities();
369                 if(null==factory) {
370                     factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
371                 }
372                 if(null==drawable) {
373                     drawable = factory.createGLDrawable(nw);
374                 }
375                 drawable.setRealized(true);
376                 context = drawable.createContext(sharedContext);
377             }
378             if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
379                 String msg = new String("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+Thread.currentThread()+", fin");
380                 System.err.println(msg);
381                 //Exception e1 = new Exception(msg);
382                 //e1.printStackTrace();
383             }
384         }
385         
386         public synchronized boolean pauseRenderingAction() {
387             boolean animatorPaused = false;
388             GLAnimatorControl ctrl = GLWindow.this.getAnimator();
389             if ( null!=ctrl ) {
390                 animatorPaused = ctrl.pause();
391             }
392             return animatorPaused;
393         }
394
395         public synchronized void resumeRenderingAction() {
396             GLAnimatorControl ctrl = GLWindow.this.getAnimator();
397             if ( null!=ctrl && ctrl.isPaused() ) {
398                 ctrl.resume();
399             }
400         }
401     }
402
403     //----------------------------------------------------------------------
404     // OpenGL-related methods and state
405     //
406
407     private GLContext sharedContext = null;
408     private GLDrawableFactory factory;
409     private GLDrawable drawable;
410     private GLContext context;
411     private GLDrawableHelper helper = new GLDrawableHelper();
412     // To make reshape events be sent immediately before a display event
413     private boolean sendReshape=false;
414     private boolean sendDestroy=false;
415     private boolean perfLog = false;
416     private long startTime, curTime, lastCheck;
417     private int  totalFrames, lastFrames;
418
419     public GLDrawableFactory getFactory() {
420         return factory;
421     }
422
423     /**
424      * Specifies an {@link javax.media.opengl.GLContext OpenGL context} to share with.<br>
425      * At native creation, {@link #setVisible(boolean) setVisible(true)},
426      * a {@link javax.media.opengl.GLDrawable drawable} and {@link javax.media.opengl.GLContext context} is created besides the native Window itself,<br>
427      * hence you shall set the shared context before.
428      *
429      * @param sharedContext The OpenGL context shared by this GLWindow's one
430      */
431     public void setSharedContext(GLContext sharedContext) {
432         this.sharedContext = sharedContext;
433     }
434
435     public void setContext(GLContext newCtx) {
436         context = newCtx;
437     }
438
439     public GLContext getContext() {
440         return context;
441     }
442
443     public GL getGL() {
444         if (context == null) {
445             return null;
446         }
447         return context.getGL();
448     }
449
450     public GL setGL(GL gl) {
451         if (context != null) {
452             context.setGL(gl);
453             return gl;
454         }
455         return null;
456     }
457
458     public void addGLEventListener(GLEventListener listener) {
459         if(null!=helper) {
460             helper.addGLEventListener(listener);
461         }
462     }
463
464     public void addGLEventListener(int index, GLEventListener listener) {
465         if(null!=helper) {
466             helper.addGLEventListener(index, listener);
467         }
468     }
469
470     public void removeGLEventListener(GLEventListener listener) {
471         if(null!=helper) {
472             helper.removeGLEventListener(listener);
473         }
474     }
475
476     public void setAnimator(GLAnimatorControl animatorControl) {
477         if(null!=helper) {
478             helper.setAnimator(animatorControl);
479         }
480     }
481
482     public GLAnimatorControl getAnimator() {
483         if(null!=helper) {
484             return helper.getAnimator();
485         }
486         return null;
487     }
488
489     public boolean getPerfLogEnabled() { return perfLog; }
490
491     public void enablePerfLog(boolean v) {
492         perfLog = v;
493     }
494
495     public void invoke(boolean wait, GLRunnable glRunnable) {
496         if(null!=helper) {
497             helper.invoke(this, wait, glRunnable);
498         }
499     }
500
501     public void display() {
502         display(false);
503     }
504
505     public void display(boolean forceReshape) {
506         if( null == window ) { return; }
507
508         if(sendDestroy || ( null!=window && window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) ) {
509             sendDestroy=false;
510             destroy();
511             return;
512         }
513
514         if( null == context && isVisible() && 0<getWidth()*getHeight() ) {
515             // retry native window and drawable/context creation 
516             setVisible(true);
517         }
518
519         if(forceReshape) {
520             sendReshape = true;
521         }
522         
523         if( isVisible() && null != context ) {
524             if( NativeSurface.LOCK_SURFACE_NOT_READY < lockSurface() ) {
525                 try {
526                     helper.invokeGL(drawable, context, displayAction, initAction);
527                 } finally {
528                     unlockSurface();
529                 }
530             }
531         }
532     }
533
534     /** This implementation uses a static value */
535     public void setAutoSwapBufferMode(boolean onOrOff) {
536         if(null!=helper) {
537             helper.setAutoSwapBufferMode(onOrOff);
538         }
539     }
540
541     /** This implementation uses a static value */
542     public boolean getAutoSwapBufferMode() {
543         if(null!=helper) {
544             return helper.getAutoSwapBufferMode();
545         }
546         return false;
547     }
548
549     public void swapBuffers() {
550         if(drawable!=null && context != null) {
551             // Lock: Locked Surface/Window by MakeCurrent/Release
552             if (context != GLContext.getCurrent()) {
553                 // Assume we should try to make the context current before swapping the buffers
554                 helper.invokeGL(drawable, context, swapBuffersAction, initAction);
555             } else {
556                 drawable.swapBuffers();
557             }
558         }
559     }
560
561     class InitAction implements Runnable {
562         public void run() {
563             // Lock: Locked Surface/Window by MakeCurrent/Release
564             helper.init(GLWindow.this);
565             resetCounter();
566         }
567     }
568     private InitAction initAction = new InitAction();
569
570     class DisplayAction implements Runnable {
571         public void run() {
572             // Lock: Locked Surface/Window by display _and_ MakeCurrent/Release
573             if (sendReshape) {
574                 helper.reshape(GLWindow.this, 0, 0, getWidth(), getHeight());
575                 sendReshape = false;
576             }
577
578             helper.display(GLWindow.this);
579
580             curTime = System.currentTimeMillis();
581             totalFrames++;
582
583             if(perfLog) {
584                 long dt0, dt1;
585                 lastFrames++;
586                 dt0 = curTime-lastCheck;
587                 if ( dt0 > 5000 ) {
588                     dt1 = curTime-startTime;
589                     System.err.println(dt0/1000 +"s: "+ lastFrames + "f, " + (lastFrames*1000)/dt0 + " fps, "+dt0/lastFrames+" ms/f; "+
590                                        "total: "+ dt1/1000+"s, "+(totalFrames*1000)/dt1 + " fps, "+dt1/totalFrames+" ms/f");
591                     lastCheck=curTime;
592                     lastFrames=0;
593                 }
594             }
595         }
596     }
597     private DisplayAction displayAction = new DisplayAction();
598
599     /** 
600      * @return Time of the first display call in milliseconds.
601      *         This value is reset if becoming visible again or reparenting.
602      */
603     public final long getStartTime()   { 
604         return startTime; 
605     }
606
607     /** 
608      * @return Time of the last display call in milliseconds.
609      *         This value is reset if becoming visible again or reparenting.
610      */
611     public final long getCurrentTime() {
612         return curTime;
613     }
614
615     /** 
616      * @return Duration <code>getCurrentTime() - getStartTime()</code>.
617      *
618      * @see #getStartTime()
619      * @see #getCurrentTime()
620      */
621     public final long getDuration() { 
622         return getCurrentTime()-getStartTime(); 
623     }
624
625     /** 
626      * @return Number of frames displayed since the first display call, ie <code>getStartTime()</code>.
627      *         This value is reset if becoming visible again or reparenting.
628      */
629     public final int getTotalFrames() { 
630         return totalFrames; 
631     }
632
633     /** Reset all counter (startTime, currentTime, frame number) */
634     public synchronized void resetCounter() {
635         startTime = System.currentTimeMillis(); // overwrite startTime to real init one
636         curTime   = startTime;
637         lastCheck  = startTime;
638         totalFrames = 0; lastFrames = 0;
639     }
640
641     class SwapBuffersAction implements Runnable {
642         public void run() {
643             drawable.swapBuffers();
644         }
645     }
646     private SwapBuffersAction swapBuffersAction = new SwapBuffersAction();
647
648     //----------------------------------------------------------------------
649     // GLDrawable methods
650     //
651
652     public final NativeSurface getNativeSurface() {
653         return null!=drawable ? drawable.getNativeSurface() : null;
654     }
655
656     public final long getHandle() {
657         return null!=drawable ? drawable.getHandle() : 0;
658     }
659
660     public final int getX() {
661         return window.getX();
662     }
663
664     public final int getY() {
665         return window.getY();
666     }
667
668     public final int getWidth() {
669         return window.getWidth();
670     }
671
672     public final int getHeight() {
673         return window.getHeight();
674     }
675
676     //----------------------------------------------------------------------
677     // GLDrawable methods that are not really needed
678     //
679
680     public final GLContext createContext(GLContext shareWith) {
681         return drawable.createContext(shareWith);
682     }
683
684     public final void setRealized(boolean realized) {
685     }
686
687     public final boolean isRealized() {
688         return ( null != drawable ) ? drawable.isRealized() : false;
689     }
690
691     public final GLCapabilitiesImmutable getChosenGLCapabilities() {
692         if (drawable == null) {
693             throw new GLException("No drawable yet");
694         }
695
696         return drawable.getChosenGLCapabilities();
697     }
698
699     public final GLProfile getGLProfile() {
700         if (drawable == null) {
701             throw new GLException("No drawable yet");
702         }
703
704         return drawable.getGLProfile();
705     }
706
707     //----------------------------------------------------------------------
708     // NEWTEventConsumer 
709     //
710     public boolean consumeEvent(NEWTEvent event) {
711         return window.consumeEvent(event);
712     }
713
714     //----------------------------------------------------------------------
715     // Window completion
716     //
717     public final void windowRepaint(int x, int y, int width, int height) {
718         window.windowRepaint(x, y, width, height);
719     }
720
721     public final void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
722         window.enqueueEvent(wait, event);
723     }
724
725     public final void runOnEDTIfAvail(boolean wait, final Runnable task) {
726         window.runOnEDTIfAvail(wait, task);
727     }
728
729     public final SurfaceUpdatedListener getSurfaceUpdatedListener(int index) {
730         return window.getSurfaceUpdatedListener(index);
731     }
732
733     public final SurfaceUpdatedListener[] getSurfaceUpdatedListeners() {
734         return window.getSurfaceUpdatedListeners();
735     }
736
737     public final void removeAllSurfaceUpdatedListener() {
738         window.removeAllSurfaceUpdatedListener();
739     }
740
741     public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
742         window.removeSurfaceUpdatedListener(l);
743     }
744
745     public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
746         window.addSurfaceUpdatedListener(l);
747     }
748
749     public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
750         window.addSurfaceUpdatedListener(index, l);
751     }
752
753     public void sendWindowEvent(int eventType) {
754         window.sendWindowEvent(eventType);
755     }
756
757     public final WindowListener getWindowListener(int index) {
758         return window.getWindowListener(index);
759     }
760
761     public final WindowListener[] getWindowListeners() {
762         return window.getWindowListeners();
763     }
764
765     public final void removeWindowListener(WindowListener l) {
766         window.removeWindowListener(l);
767     }
768
769     public final void addWindowListener(WindowListener l) {
770         window.addWindowListener(l);
771     }
772
773     public final void addWindowListener(int index, WindowListener l) throws IndexOutOfBoundsException {
774         window.addWindowListener(index, l);
775     }
776
777     public final void addKeyListener(KeyListener l) {
778         window.addKeyListener(l);
779     }
780
781     public final void addKeyListener(int index, KeyListener l) {
782         window.addKeyListener(index, l);
783     }
784
785     public final void removeKeyListener(KeyListener l) {
786         window.removeKeyListener(l);
787     }
788
789     public final KeyListener getKeyListener(int index) {
790         return window.getKeyListener(index);
791     }
792
793     public final KeyListener[] getKeyListeners() {
794         return window.getKeyListeners();
795     }
796
797     public final void addMouseListener(MouseListener l) {
798         window.addMouseListener(l);
799     }
800
801     public final void addMouseListener(int index, MouseListener l) {
802         window.addMouseListener(index, l);
803     }
804
805     public final void removeMouseListener(MouseListener l) {
806         window.removeMouseListener(l);
807     }
808
809     public final MouseListener getMouseListener(int index) {
810         return window.getMouseListener(index);
811     }
812
813     public final MouseListener[] getMouseListeners() {
814         return window.getMouseListeners();
815     }
816
817     //----------------------------------------------------------------------
818     // NativeWindow completion
819     //
820
821     public final int lockSurface() {
822         return window.lockSurface();
823     }
824
825     public final void unlockSurface() throws NativeWindowException {
826         window.unlockSurface();
827     }
828
829     public final boolean isSurfaceLockedByOtherThread() {
830         return window.isSurfaceLockedByOtherThread();
831     }
832
833     public final boolean isSurfaceLocked() {
834         return window.isSurfaceLocked();
835     }
836
837     public final Thread getSurfaceLockOwner() {
838         return window.getSurfaceLockOwner();
839
840     }
841
842     public final boolean surfaceSwap() {
843         return window.surfaceSwap();
844     }
845
846     public final void invalidate() {
847         window.invalidate();
848     }
849     
850     public final long getWindowHandle() {
851         return window.getWindowHandle();
852
853     }
854
855     public final long getSurfaceHandle() {
856         return window.getSurfaceHandle();
857
858     }
859
860     public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
861         return window.getGraphicsConfiguration();
862     }
863
864     public final long getDisplayHandle() {
865         return window.getDisplayHandle();
866     }
867
868     public final int  getScreenIndex() {
869         return window.getScreenIndex();
870     }
871
872     public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
873         window.surfaceUpdated(updater, ns, when);
874     }
875
876     /**
877      * A most simple JOGL AWT test entry
878      */
879     public static void main(String args[]) {
880         System.err.println(VersionUtil.getPlatformInfo());
881         System.err.println(GlueGenVersion.getInstance());
882         System.err.println(NativeWindowVersion.getInstance());
883         System.err.println(JoglVersion.getInstance());
884         System.err.println(NewtVersion.getInstance());
885         GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault() );
886
887         GLWindow glWindow = GLWindow.create(caps);
888         glWindow.setSize(128, 128);
889
890         glWindow.addGLEventListener(new GLEventListener() {
891             public void init(GLAutoDrawable drawable) {
892                 GL gl = drawable.getGL();
893                 System.err.println(JoglVersion.getInstance().getGLInfo(gl, null));
894             }
895
896             public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
897             }
898
899             public void display(GLAutoDrawable drawable) {
900             }
901
902             public void dispose(GLAutoDrawable drawable) {
903             }
904         });
905
906         glWindow.setVisible(true);
907         glWindow.invalidate();
908     }
909
910 }
http://JogAmp.org git info: FAQ, tutorial and man pages.