Jogamp
Fix Window destroyNotify() -> QUIT
[users/sgothel/jake2.git] / src / jake2 / render / opengl / NEWTWin.java
1 /*
2  * NEWTWin.java
3  * Copyright (C) 2004
4  * 
5  */
6 package jake2.render.opengl;
7
8 import jake2.Defines;
9 import jake2.Globals;
10 import jake2.SizeChangeListener;
11 import jake2.client.VID;
12 import jake2.game.cvar_t;
13 import jake2.qcommon.Cbuf;
14 import jake2.qcommon.Cvar;
15 import jake2.render.Base;
16 import jake2.sys.NEWTKBD;
17
18 import java.util.List;
19
20 import javax.media.nativewindow.CapabilitiesChooser;
21 import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
22 import javax.media.nativewindow.util.Dimension;
23 import javax.media.nativewindow.util.DimensionImmutable;
24 import javax.media.nativewindow.util.SurfaceSize;
25 import javax.media.opengl.GLCapabilities;
26 import javax.media.opengl.GLContext;
27 import javax.media.opengl.GLProfile;
28
29 import jogamp.opengl.FPSCounterImpl;
30
31 import com.jogamp.common.os.Platform;
32 import com.jogamp.newt.*;
33 import com.jogamp.newt.event.WindowAdapter;
34 import com.jogamp.newt.event.WindowEvent;
35 import com.jogamp.newt.opengl.GLWindow;
36 import com.jogamp.newt.util.MonitorModeUtil;
37 import com.jogamp.opengl.GenericGLCapabilitiesChooser;
38
39 public class NEWTWin {
40     MonitorMode oldDisplayMode = null;
41     volatile Screen screen = null;
42     volatile GLWindow window = null;
43     volatile boolean shouldQuit = false;
44     final FPSCounterImpl fpsCounter = new FPSCounterImpl();
45
46     public List<MonitorMode> getModeList() {
47         if( null != window ) {
48             final MonitorDevice mainMonitor = window.getMainMonitor();
49             return mainMonitor.getSupportedModes();
50         } else {        
51             return screen.getMonitorModes();
52         }
53     }
54
55     public MonitorMode findDisplayMode(DimensionImmutable dim) {
56         final List<MonitorMode> sml = MonitorModeUtil.filterByResolution(getModeList(), dim);
57         if(sml.size() == 0) {
58             return oldDisplayMode;
59         }
60         return sml.get(0);
61     }
62
63     public String getModeString(MonitorMode mm) {
64         final SurfaceSize ss = mm.getSurfaceSize();
65         final DimensionImmutable m = ss.getResolution();
66         final StringBuffer sb = new StringBuffer();
67         sb.append(m.getWidth());
68         sb.append('x');
69         sb.append(m.getHeight());
70         sb.append('x');
71         sb.append(ss.getBitsPerPixel());
72         sb.append('@');
73         sb.append(mm.getRefreshRate());
74         sb.append("Hz");
75         return sb.toString();
76     }
77
78     /**
79      * @param dim
80      * @param mode
81      * @param fullscreen
82      * @param driverName TODO
83      * @return enum Base.rserr_t
84      */
85     public int setMode(GLProfile glp, Dimension dim, int mode, boolean fullscreen, String driverName) {
86         final boolean isARM = Platform.CPUFamily.ARM == Platform.getCPUFamily();
87
88         final Dimension newDim = new Dimension();
89
90         VID.Printf(Defines.PRINT_ALL, "Initializing OpenGL display for profile "+glp+"\n");
91
92         if(null == screen) {
93             screen = NewtFactory.createScreen(NewtFactory.createDisplay(null), 0);
94             screen.addReference(); // trigger native creation
95         } else if( !screen.isNativeValid() ) {
96             screen.addReference(); // trigger native creation
97         }
98         
99         if (!VID.GetModeInfo(newDim, mode)) {
100             VID.Printf(Defines.PRINT_ALL, " invalid mode\n");
101             return Base.rserr_invalid_mode;
102         }
103
104         VID.Printf(Defines.PRINT_ALL, "...setting mode " + mode + ", " + newDim.getWidth() + " x " + newDim.getHeight() + ", fs " + fullscreen + ", driver " + driverName + "\n");
105
106         // destroy the existing window, not screen
107         shutdownImpl(false);
108         
109         if(null != window) {
110             throw new InternalError("XXX");            
111         }
112         final GLCapabilities caps = new GLCapabilities(glp);
113         CapabilitiesChooser chooser = null; // default
114         {
115             final cvar_t v = Cvar.Get("jogl_rgb565", "0", 0);
116             if( v.value != 0f ) {
117                 caps.setRedBits(5);
118                 caps.setGreenBits(6);
119                 caps.setBlueBits(5);
120                 chooser = new GenericGLCapabilitiesChooser(); // don't trust native GL-TK chooser
121             }
122         }
123         window = GLWindow.create(screen, caps);
124         window.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); // we do handle QUIT on our own, no GLWindow.display() called.
125         window.setCapabilitiesChooser(chooser);
126         window.addWindowListener(new WindowAdapter() {
127             public void windowDestroyNotify(WindowEvent e) {
128                 shouldQuit = !Globals.appletMode && null != window; // not applet and not already in shutdown ?
129             }
130
131             public void windowResized(WindowEvent e) {
132                 propagateNewSize();
133             }
134         });
135         window.setTitle("Jake2 ("+driverName+"-newt-"+glp.getName().toLowerCase()+")");
136
137         final MonitorDevice mainMonitor = window.getMainMonitor();
138         
139         if (oldDisplayMode == null) {
140             oldDisplayMode = mainMonitor.getCurrentMode();
141         }
142
143         // We need to feed the NEWT Window to the NEWTKBD
144         NEWTKBD.Init(window);
145         
146         window.addWindowListener(NEWTKBD.listener);
147         window.addKeyListener(NEWTKBD.listener);
148         window.addMouseListener(NEWTKBD.listener);
149
150         if (fullscreen) {
151             MonitorMode mm = findDisplayMode(newDim);
152             final DimensionImmutable smDim = mm.getSurfaceSize().getResolution();
153             newDim.setWidth( smDim.getWidth() );
154             newDim.setHeight( smDim.getHeight() );
155             mainMonitor.setCurrentMode(mm);
156             window.setFullscreen(true);
157         } else {
158             window.setSize(newDim.getWidth(), newDim.getHeight());
159             if (Globals.appletMode) {
160                 // Notify the size listener about the change
161                 final SizeChangeListener listener = Globals.sizeChangeListener;
162                 if (listener != null) {
163                     listener.sizeChanged(newDim.getWidth(), newDim.getHeight());
164                 }
165             }
166         }
167         window.setVisible(true);
168
169         if (!Globals.appletMode) {
170             while ( !window.isNativeValid()|| !window.isRealized() ) {
171                 try {
172                     Thread.sleep(100);
173                 } catch (InterruptedException e) {}
174             }
175         }
176         window.requestFocus();
177         window.display(); // force GL resource validation
178         window.setAutoSwapBufferMode(false);
179
180         VID.Printf(Defines.PRINT_ALL, "...reques GLCaps "+window.getRequestedCapabilities()+'\n');
181         VID.Printf(Defines.PRINT_ALL, "...chosen GLCaps "+window.getChosenGLCapabilities()+'\n');
182         VID.Printf(Defines.PRINT_ALL, "...size "+window.getWidth()+" x "+window.getHeight()+'\n');
183         fpsCounter.setUpdateFPSFrames(isARM ? 60 : 4*60, System.err);
184
185         // propagateNewSize("init");
186         activateGLContext();
187         
188         return Base.rserr_ok;
189     }
190     
191     private void propagateNewSize() {
192         final int width = window.getWidth();
193         final int height = window.getHeight();
194         final int _width;
195         final int mask = ~0x03;
196         if ((width & 0x03) != 0) {
197             _width = ( width & mask ) + 4;
198         } else {
199             _width = width;
200         }
201         VID.Printf(Defines.PRINT_ALL, "Resize: " + width + " x " + height + ", masked " + _width + "x" + height + "\n");  
202
203         Base.setVid(_width, height);
204         // let the sound and input subsystems know about the new window
205         VID.NewWindow(_width, height);                    
206     }
207
208     protected final void activateGLContext() {
209         final GLContext ctx = window.getContext();
210         if ( null != ctx && GLContext.getCurrent() != ctx ) {                
211             ctx.makeCurrent();
212         }
213     }
214     
215     protected final void deactivateGLContext() {
216         final GLContext ctx = window.getContext();
217         if ( null != ctx && GLContext.getCurrent() == ctx) {
218             ctx.release();
219         }        
220     }
221     
222     /** Performs {@link GLWindow#swapBuffers()}, ticks the fps counter and performs <code>QUIT</code> if requested. */
223     public final void endFrame() {
224         window.swapBuffers();
225         fpsCounter.tickFPS();
226         if( shouldQuit ) {
227             deactivateGLContext();
228             Cbuf.ExecuteText(Defines.EXEC_APPEND, "quit");
229         }
230     }
231     /** Performs <code>QUIT</code> if requested. */
232     public final void checkQuit() {
233         if( shouldQuit ) {
234             deactivateGLContext();
235             Cbuf.ExecuteText(Defines.EXEC_APPEND, "quit");
236         }
237     }
238     
239     void shutdown() {
240         shutdownImpl(true);
241     }
242     
243     private void shutdownImpl(boolean withScreen) {
244         if ( null != window ) {
245             deactivateGLContext();
246             final GLWindow _window = window;
247             window = null;
248             _window.destroy(); // same thing
249         }
250         if( withScreen && null != screen ) {
251             screen.destroy();
252             screen = null;
253         }
254     }    
255     
256 }
http://JogAmp.org git info: FAQ, tutorial and man pages.