Jogamp
Add Applet Feature incl. required fixes.
authorSven Gothel <sgothel@jausoft.com>
Fri, 28 Jun 2013 17:06:14 +0000 (19:06 +0200)
committerSven Gothel <sgothel@jausoft.com>
Fri, 28 Jun 2013 17:06:14 +0000 (19:06 +0200)
- Jake2Applet
  - Reenable JavaScript Bridge to resize Applet
  - Pass through 4:3 aspect custom video mode (Jake2 args)
  - Pass through applet parameter 'jake_args' (Jake2 args)
  - OSX Hack: Re-create Game at init, otherwise flickering appears (??)

- Fix VID.init: Set vid_ref.modifier = true, otherwise not guaranteed VID creation

- BeginFrame, R_BeginFrame, beginFrame, activateGLContext:
  Return 'true', if ctx is available, otherwise false to skip frame.

- NEWTWin:
  - Applet mode (in Applet container): Always release GL ctx

  - Use GLAnimatorControl impl, to state whether we are animating or not
    and to tell us, whether we have to release the GL ctx.

  - Add HOME -> Reparent feature for Applets
    - Workaround for NEWT/Windows Bug 798

- NEWT Key Handling:
  - Ignore auto-repeat
  - Workaround for NEWT/Windows Bug 798

- Add HTML page
  - normal
  - debug mode

26 files changed:
src/jake2/Jake2Applet.java
src/jake2/client/SCR.java
src/jake2/client/VID.java
src/jake2/client/refexport_t.java
src/jake2/render/DummyRenderer.java
src/jake2/render/JoglDummyRenderer.java
src/jake2/render/JoglES1Renderer.java
src/jake2/render/JoglES2Renderer.java
src/jake2/render/JoglGL2Renderer.java
src/jake2/render/RenderAPI.java
src/jake2/render/basic/Main.java
src/jake2/render/fast/Main.java
src/jake2/render/opengl/GLDriver.java
src/jake2/render/opengl/JoglDummyDriver.java
src/jake2/render/opengl/JoglES1Driver.java
src/jake2/render/opengl/JoglES2Driver.java
src/jake2/render/opengl/JoglGL2Driver.java
src/jake2/render/opengl/NEWTWin.java
src/jake2/sys/InputListener.java
src/jake2/sys/NEWTKBD.java
src/jake2/sys/Sys.java
webstart/jake2-napplet01.html [new file with mode: 0644]
webstart/jake2-napplet01_dbg.html [new file with mode: 0644]
webstart/jake2_online.jnlp
webstart/old/jake2_jogl11.jnlp [moved from webstart/jake2_jogl11.jnlp with 100% similarity]
webstart/old/jake2_lwjgl.jnlp [moved from webstart/jake2_lwjgl.jnlp with 100% similarity]

index 91ce077..e444ebc 100755 (executable)
@@ -29,107 +29,185 @@ import jake2.game.Cmd;
 import jake2.qcommon.*;
 import jake2.sys.Timer;
 
-import java.awt.BorderLayout;
-import java.awt.Color;
+import java.applet.Applet;
+import java.awt.*;
+import java.util.StringTokenizer;
 
-import javax.swing.JApplet;
+import com.jogamp.common.os.Platform;
 
-// import netscape.javascript.*;
+import netscape.javascript.*;
 
 /**
  * Jake2 is the main class of Quake2 for Java.
  */
 @SuppressWarnings("serial")
-public class Jake2Applet extends JApplet {
+public class Jake2Applet extends Applet {
 
-    // FIXME private JSObject self;
-    private volatile boolean shouldShutDown;
-    private boolean shutDown;
-    private Object shutDownLock = new Object();
+    private JSObject self;
+    private volatile boolean gameShouldShutDown;
+    private volatile boolean gameShutDown;
+    private volatile boolean gameStarted;
+    private Object gameLifecycleLock = new Object();
+    
+    private static String sz0_args = " +set gl_mode 11 +set vid_width ";
+    private static String sz1_args = " +set vid_height ";
 
+    @Override
     public void init() {
-        // Before Jake2 is fully initialized, make the applet black
-        // like the rest of the web page
-        setBackground(Color.BLACK);
+        System.err.println("Jake2 Applet Init: "+Thread.currentThread().getName());
+        setBackground(new Color(0x33, 0x33, 0x33, 0xff)); // web page
+        setLayout(new java.awt.BorderLayout());
     }
 
+    @Override
     public void start() {
-        setLayout(new BorderLayout());
-        new GameThread().start();
+        System.err.println("Jake2 Applet Start.0: "+Thread.currentThread().getName());
+        synchronized(gameLifecycleLock) {
+            gameShouldShutDown = false;
+            gameShutDown = false;
+            gameStarted = false;
+        }
+        if( EventQueue.isDispatchThread() ) { // Game thread offloads to AWT-EDT in Applet mode
+            new GameThread().start();            
+        } else {
+            synchronized(gameLifecycleLock) {
+                new GameThread().start();
+                while (!gameStarted) {
+                    try {
+                        gameLifecycleLock.wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+        }
+        System.err.println("Jake2 Applet Start.X: "+Thread.currentThread().getName());
     }
 
+    @Override
     public void stop() {
-        synchronized(shutDownLock) {
-            shouldShutDown = true;
-            while (!shutDown) {
+        System.err.println("Jake2 Applet Stop.0: "+Thread.currentThread().getName());
+        synchronized(gameLifecycleLock) {
+            gameShouldShutDown = true;
+            while (!gameShutDown) {
                 try {
-                    shutDownLock.wait();
+                    gameLifecycleLock.wait();
                 } catch (InterruptedException e) {
                 }
             }
         }
-        Cmd.ExecuteString("quit");
+        System.err.println("Jake2 Applet Stop.X: "+Thread.currentThread().getName());
     }
-
+    
+    @Override
+    public void destroy() {
+        System.err.println("Jake2 Applet Destroy.0: "+Thread.currentThread().getName());
+    }
+    
     class GameThread extends Thread {
         public GameThread() {
             super("Jake2 Game Thread");
         }
 
         public void run() {
-            // TODO: check if dedicated is set in config file
-       
-            Globals.dedicated= Cvar.Get("dedicated", "0", Qcommon.CVAR_NOSET);
-    
-            // Set things up for applet execution
-            Qcommon.appletMode = true;
-            Qcommon.applet = Jake2Applet.this;
-            Qcommon.sizeChangeListener = new SizeChangeListener() {
-                    public void sizeChanged(int width, int height) {
-                        /** FIXME
-                        try {
-                            if (self == null) {
-                                JSObject win = JSObject.getWindow(Jake2Applet.this);
-                                self = (JSObject) win.eval("document.getElementById(\"" +
-                                                           getParameter("id") + "\")");
+            synchronized(gameLifecycleLock) {
+                // TODO: check if dedicated is set in config file
+               
+                System.err.println("Jake2 Applet Game START: "+Thread.currentThread().getName());
+                
+                Globals.dedicated= Cvar.Get("dedicated", "0", Qcommon.CVAR_NOSET);
+        
+                // Set things up for applet execution
+                Globals.appletMode = true;
+                Globals.applet = Jake2Applet.this;
+                Globals.sizeChangeListener = new SizeChangeListener() {
+                        public void sizeChanged(int width, int height) {
+                            try {
+                                if (self == null) {
+                                    JSObject win = JSObject.getWindow(Jake2Applet.this);
+                                    self = (JSObject) win.eval("document.getElementById(\"" +
+                                                               getParameter("id") + "\")");
+                                }
+                                self.setMember("width", new Integer(width));
+                                self.setMember("height", new Integer(height));
+                            } catch (Exception e) {
+                                e.printStackTrace();
                             }
-
-                            self.setMember("width", new Integer(width));
-                            self.setMember("height", new Integer(height));
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                        } */
+                        }
+                    };
+    
+                // open the q2dialog, if we are not in dedicated mode.
+                if (Globals.dedicated.value != 1.0f) {
+                    Jake2.initQ2DataTool();
+                }
+                
+                final int a_width = Jake2Applet.this.getWidth();
+                final int a_height = (int) ( a_width * 0.75f );
+    
+                final String cmd_args;
+                {
+                    final String applet_args = getParameter("jake_args");
+                    StringBuffer sb = new StringBuffer();                
+                    sb.append("Jake2 ");
+                    if( null != applet_args && applet_args.length() > 0 ) {
+                        sb.append(applet_args);
                     }
-                };
-
-            // open the q2dialog, if we are not in dedicated mode.
-            if (Globals.dedicated.value != 1.0f) {
-                Jake2.initQ2DataTool();
+                    sb.append(sz0_args);
+                    sb.append(a_width);
+                    sb.append(sz1_args);
+                    sb.append(a_height);
+                    cmd_args = sb.toString();
+                }
+                System.err.println("Jake2 Applet Cmd: "+cmd_args);
+                final String[] c_args;
+                StringTokenizer tokens = new StringTokenizer(cmd_args);
+                final int argc = tokens.countTokens();
+                c_args = new String[argc];
+                int i=0;
+                while( tokens.hasMoreTokens() ) {
+                    c_args[i++] = tokens.nextToken().trim();
+                }
+                
+                Qcommon.Init(c_args);
+                if( Platform.OSType.MACOS == Platform.getOSType() ) {
+                    // FIXME: Bug on OSX: 1st NewtCanvasAWT added .. causes flickering, so 'do it again'.
+                    // Interesting that our JOGLNewtApplet1Run does not suffer from this behavior!
+                    Cmd.ExecuteString("quit");
+                    Qcommon.Init(c_args);
+                }
+                Globals.nostdout = Cvar.Get("nostdout", "0", 0);
+                
+                gameStarted = true;
+                gameLifecycleLock.notifyAll();
             }
 
-            Qcommon.Init(new String[] { "Jake2" });
-
-            Globals.nostdout = Cvar.Get("nostdout", "0", 0);
-
             try {
-                while (!shouldShutDown) {
-                    int oldtime = Timer.Milliseconds();
-                    int newtime;
-                    int time;
-                    while (true) {
-                        // find time spending rendering last frame
-                        newtime = Timer.Milliseconds();
-                        time = newtime - oldtime;
-
-                        if (time > 0)
-                            Qcommon.Frame(time);
-                        oldtime = newtime;
+                int oldtime = Timer.Milliseconds();
+                while (!gameShouldShutDown) {
+                    // find time spending rendering last frame
+                    final int newtime = Timer.Milliseconds();
+                    final int time = newtime - oldtime;
+
+                    if (time > 0) {
+                        Qcommon.Frame(time);
                     }
+                    oldtime = newtime;
                 }
+            } catch(Throwable t) {
+                System.err.println("Jake2 Applet Game Exception: "+t.getClass().getName()+": "+t.getMessage());
+                t.printStackTrace();
             } finally {
-                synchronized(shutDownLock) {
-                    shutDown = true;
-                    shutDownLock.notifyAll();
+                synchronized(gameLifecycleLock) {
+                    System.err.println("Jake2 Applet Game STOP.0: "+Thread.currentThread().getName());
+                    try {
+                        Cmd.ExecuteString("quit");
+                    } catch (Exception e) {
+                        System.err.println("Jake2 Applet Game STOP Catched:");
+                        e.printStackTrace();
+                    }
+                    gameShutDown = true;
+                    gameStarted = false;
+                    gameLifecycleLock.notifyAll();
+                    System.err.println("Jake2 Applet Game STOP.X: "+Thread.currentThread().getName());
                 }
             }
         }
index 50cd74c..937b293 100644 (file)
@@ -286,10 +286,9 @@ public final class SCR extends Globals {
         int x, y;
         int remaining;
 
-        if (cs == null)
-            return;
-        if (cs.length() == 0)
+        if (cs.length() == 0) {
             return;
+        }
 
         // the finale prints the characters one at a time
         remaining = 9999;
@@ -621,19 +620,21 @@ public final class SCR extends Globals {
         start = Timer.Milliseconds();
 
         if (Cmd.Argc() == 2) { // run without page flipping
-            re.BeginFrame(0);
-            for (i = 0; i < 128; i++) {
-                cl.refdef.viewangles[1] = i / 128.0f * 360.0f;
-                re.RenderFrame(cl.refdef);
+            if ( re.BeginFrame(0) ) {
+                for (i = 0; i < 128; i++) {
+                    cl.refdef.viewangles[1] = i / 128.0f * 360.0f;
+                    re.RenderFrame(cl.refdef);
+                }
+                re.EndFrame();
             }
-            re.EndFrame();
         } else {
             for (i = 0; i < 128; i++) {
                 cl.refdef.viewangles[1] = i / 128.0f * 360.0f;
 
-                re.BeginFrame(0);
-                re.RenderFrame(cl.refdef);
-                re.EndFrame();
+                if( re.BeginFrame(0) ) {
+                    re.RenderFrame(cl.refdef);
+                    re.EndFrame();
+                }
             }
         }
 
@@ -1206,79 +1207,85 @@ public final class SCR extends Globals {
             numframes = 1;
         }
 
+        boolean frameRendered = false;
+        
         for (i = 0; i < numframes; i++) {
-            re.BeginFrame(separation[i]);
-
-            if (scr_draw_loading == 2) { //  loading plaque over black screen
-                Dimension dim = new Dimension();
-
-                re.CinematicSetPalette(null);
-                scr_draw_loading = 0; // false
-                re.DrawGetPicSize(dim, "loading");
-                re.DrawPic((viddef.getWidth() - dim.getWidth()) / 2,
-                        (viddef.getHeight() - dim.getHeight()) / 2, "loading");
-            }
-            // if a cinematic is supposed to be running, handle menus
-            // and console specially
-            else if (cl.cinematictime > 0) {
-                if (cls.key_dest == key_menu) {
-                    if (cl.cinematicpalette_active) {
-                        re.CinematicSetPalette(null);
-                        cl.cinematicpalette_active = false;
+            if ( re.BeginFrame(separation[i]) ) {
+                frameRendered = true;
+                
+                if (scr_draw_loading == 2) { //  loading plaque over black screen
+                    Dimension dim = new Dimension();
+    
+                    re.CinematicSetPalette(null);
+                    scr_draw_loading = 0; // false
+                    re.DrawGetPicSize(dim, "loading");
+                    re.DrawPic((viddef.getWidth() - dim.getWidth()) / 2,
+                            (viddef.getHeight() - dim.getHeight()) / 2, "loading");
+                }
+                // if a cinematic is supposed to be running, handle menus
+                // and console specially
+                else if (cl.cinematictime > 0) {
+                    if (cls.key_dest == key_menu) {
+                        if (cl.cinematicpalette_active) {
+                            re.CinematicSetPalette(null);
+                            cl.cinematicpalette_active = false;
+                        }
+                        Menu.Draw();
+                    } else if (cls.key_dest == key_console) {
+                        if (cl.cinematicpalette_active) {
+                            re.CinematicSetPalette(null);
+                            cl.cinematicpalette_active = false;
+                        }
+                        DrawConsole();
+                    } else {
+                        // TODO implement cinematics completely
+                        DrawCinematic();
                     }
-                    Menu.Draw();
-                } else if (cls.key_dest == key_console) {
+                } else {
+                    // make sure the game palette is active
                     if (cl.cinematicpalette_active) {
                         re.CinematicSetPalette(null);
                         cl.cinematicpalette_active = false;
                     }
+    
+                    // do 3D refresh drawing, and then update the screen
+                    CalcVrect();
+    
+                    // clear any dirty part of the background
+                    TileClear();
+    
+                    V.RenderView(separation[i]);
+    
+                    DrawStats();
+    
+                    if ((cl.frame.playerstate.stats[STAT_LAYOUTS] & 1) != 0)
+                        DrawLayout();
+                    if ((cl.frame.playerstate.stats[STAT_LAYOUTS] & 2) != 0)
+                        CL_inv.DrawInventory();
+    
+                    DrawNet();
+                    CheckDrawCenterString();
+                    DrawFPS();
+    
+                    //
+                    //                         if (scr_timegraph->value)
+                    //                                 SCR_DebugGraph (cls.frametime*300, 0);
+                    //
+                    //                         if (scr_debuggraph->value || scr_timegraph->value ||
+                    // scr_netgraph->value)
+                    //                                 SCR_DrawDebugGraph ();
+                    //
+                    DrawPause();
                     DrawConsole();
-                } else {
-                    // TODO implement cinematics completely
-                    DrawCinematic();
-                }
-            } else {
-                // make sure the game palette is active
-                if (cl.cinematicpalette_active) {
-                    re.CinematicSetPalette(null);
-                    cl.cinematicpalette_active = false;
+                    Menu.Draw();
+                    DrawLoading();
                 }
-
-                // do 3D refresh drawing, and then update the screen
-                CalcVrect();
-
-                // clear any dirty part of the background
-                TileClear();
-
-                V.RenderView(separation[i]);
-
-                DrawStats();
-
-                if ((cl.frame.playerstate.stats[STAT_LAYOUTS] & 1) != 0)
-                    DrawLayout();
-                if ((cl.frame.playerstate.stats[STAT_LAYOUTS] & 2) != 0)
-                    CL_inv.DrawInventory();
-
-                DrawNet();
-                CheckDrawCenterString();
-                DrawFPS();
-
-                //
-                //                             if (scr_timegraph->value)
-                //                                     SCR_DebugGraph (cls.frametime*300, 0);
-                //
-                //                             if (scr_debuggraph->value || scr_timegraph->value ||
-                // scr_netgraph->value)
-                //                                     SCR_DrawDebugGraph ();
-                //
-                DrawPause();
-                DrawConsole();
-                Menu.Draw();
-                DrawLoading();
             }
         }
 
-        Globals.re.EndFrame();
+        if( frameRendered ) {
+            Globals.re.EndFrame();
+        }
     }
 
     /*
index d34a967..04bbf08 100644 (file)
@@ -327,11 +327,12 @@ public class VID extends Globals {
                                Restart_f();
                        }
                });
-
+               
                /* Disable the 3Dfx splash screen */
                // putenv("FX_GLIDE_NO_SPLASH=0");
                
                /* Start the graphics mode and load refresh DLL */
+                vid_ref.modified = true;
                CheckChanges();
        }
 
index 2238e4b..e89aa37 100644 (file)
@@ -97,7 +97,7 @@ public interface refexport_t {
        */
        /* 256 r,g,b values;    null = game palette, size = 768 bytes */
        void CinematicSetPalette(final byte[] palette);
-       void BeginFrame(float camera_separation);
+       boolean BeginFrame(float camera_separation);
        void EndFrame();
 
        void AppActivate(boolean activate);
index fcef2fd..07a3002 100644 (file)
@@ -141,7 +141,8 @@ public class DummyRenderer implements refexport_t {
        /* (non-Javadoc)
         * @see jake2.client.refexport_t#BeginFrame(float)
         */
-       public void BeginFrame(float camera_separation) {
+       public boolean BeginFrame(float camera_separation) {
+           return true;
        }
 
        /* (non-Javadoc)
index e39bd23..cdd3cbb 100644 (file)
@@ -73,7 +73,7 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
         // pre init, reads Cvar's
         if (!impl.R_Init(vid_xpos, vid_ypos)) return false;
         // activates the OpenGL context        
-        activateGLContext();
+        activateGLContext(true);
         
         // post init        
         return impl.R_Init2();
@@ -90,7 +90,7 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
      * @see jake2.client.refexport_t#BeginRegistration(java.lang.String)
      */
     public final void BeginRegistration(String map) {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_BeginRegistration(map);
     }
 
@@ -98,7 +98,7 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
      * @see jake2.client.refexport_t#RegisterModel(java.lang.String)
      */
     public final model_t RegisterModel(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.R_RegisterModel(name);
     }
 
@@ -106,7 +106,7 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
      * @see jake2.client.refexport_t#RegisterSkin(java.lang.String)
      */
     public final image_t RegisterSkin(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.R_RegisterSkin(name);
     }
 
@@ -114,14 +114,14 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
      * @see jake2.client.refexport_t#RegisterPic(java.lang.String)
      */
     public final image_t RegisterPic(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.Draw_FindPic(name);
     }
     /** 
      * @see jake2.client.refexport_t#SetSky(java.lang.String, float, float[])
      */
     public final void SetSky(String name, float rotate, float[] axis) {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_SetSky(name, rotate, axis);
     }
 
@@ -129,7 +129,7 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
      * @see jake2.client.refexport_t#EndRegistration()
      */
     public final void EndRegistration() {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_EndRegistration();
     }
 
@@ -165,7 +165,7 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
      * @see jake2.client.refexport_t#DrawChar(int, int, int)
      */
     public final void DrawChar(int x, int y, int num) {
-        activateGLContext();
+        activateGLContext(true);
         impl.Draw_Char(x, y, num);
     }
 
@@ -207,8 +207,8 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
     /** 
      * @see jake2.client.refexport_t#BeginFrame(float)
      */
-    public final void BeginFrame(float camera_separation) {
-        impl.R_BeginFrame(camera_separation);
+    public final boolean BeginFrame(float camera_separation) {
+        return impl.R_BeginFrame(camera_separation);
     }
 
     /** 
@@ -226,7 +226,7 @@ final class JoglDummyRenderer extends JoglDummyDriver implements refexport_t, Re
     }
 
     public void screenshot() {
-        activateGLContext();
+        activateGLContext(true);
         impl.GL_ScreenShot_f();
     }
 
index f798857..59399ea 100644 (file)
@@ -73,7 +73,7 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
             return false;
         }
         // activates the OpenGL context        
-        activateGLContext();
+        activateGLContext(true);
         
         // post init        
         return impl.R_Init2();
@@ -90,7 +90,7 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#BeginRegistration(java.lang.String)
      */
     public final void BeginRegistration(String map) {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_BeginRegistration(map);
     }
 
@@ -98,7 +98,7 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterModel(java.lang.String)
      */
     public final model_t RegisterModel(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.R_RegisterModel(name);
     }
 
@@ -106,7 +106,7 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterSkin(java.lang.String)
      */
     public final image_t RegisterSkin(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.R_RegisterSkin(name);
     }
 
@@ -114,14 +114,14 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterPic(java.lang.String)
      */
     public final image_t RegisterPic(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.Draw_FindPic(name);
     }
     /** 
      * @see jake2.client.refexport_t#SetSky(java.lang.String, float, float[])
      */
     public final void SetSky(String name, float rotate, float[] axis) {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_SetSky(name, rotate, axis);
     }
 
@@ -129,7 +129,7 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#EndRegistration()
      */
     public final void EndRegistration() {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_EndRegistration();
     }
 
@@ -165,7 +165,7 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#DrawChar(int, int, int)
      */
     public final void DrawChar(int x, int y, int num) {
-        activateGLContext();
+        activateGLContext(true);
         impl.Draw_Char(x, y, num);
     }
 
@@ -207,8 +207,8 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
     /** 
      * @see jake2.client.refexport_t#BeginFrame(float)
      */
-    public final void BeginFrame(float camera_separation) {
-        impl.R_BeginFrame(camera_separation);
+    public final boolean BeginFrame(float camera_separation) {
+        return impl.R_BeginFrame(camera_separation);
     }
 
     /** 
@@ -226,7 +226,7 @@ final class JoglES1Renderer extends JoglES1Driver implements refexport_t, Ref {
     }
 
     public void screenshot() {
-        activateGLContext();
+        activateGLContext(true);
         impl.GL_ScreenShot_f();
     }
 
index a832ac1..f81000f 100644 (file)
@@ -71,7 +71,7 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
         // pre init, reads Cvar's
         if (!impl.R_Init(vid_xpos, vid_ypos)) return false;
         // activates the OpenGL context        
-        activateGLContext();
+        activateGLContext(true);
         
         // post init        
         return impl.R_Init2();
@@ -88,7 +88,7 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#BeginRegistration(java.lang.String)
      */
     public final void BeginRegistration(String map) {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_BeginRegistration(map);
     }
 
@@ -96,7 +96,7 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterModel(java.lang.String)
      */
     public final model_t RegisterModel(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.R_RegisterModel(name);
     }
 
@@ -104,7 +104,7 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterSkin(java.lang.String)
      */
     public final image_t RegisterSkin(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.R_RegisterSkin(name);
     }
 
@@ -112,14 +112,14 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterPic(java.lang.String)
      */
     public final image_t RegisterPic(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.Draw_FindPic(name);
     }
     /** 
      * @see jake2.client.refexport_t#SetSky(java.lang.String, float, float[])
      */
     public final void SetSky(String name, float rotate, float[] axis) {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_SetSky(name, rotate, axis);
     }
 
@@ -127,7 +127,7 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#EndRegistration()
      */
     public final void EndRegistration() {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_EndRegistration();
     }
 
@@ -163,7 +163,7 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#DrawChar(int, int, int)
      */
     public final void DrawChar(int x, int y, int num) {
-        activateGLContext();
+        activateGLContext(true);
         impl.Draw_Char(x, y, num);
     }
 
@@ -205,8 +205,8 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
     /** 
      * @see jake2.client.refexport_t#BeginFrame(float)
      */
-    public final void BeginFrame(float camera_separation) {
-        impl.R_BeginFrame(camera_separation);
+    public final boolean BeginFrame(float camera_separation) {
+        return impl.R_BeginFrame(camera_separation);
     }
 
     /** 
@@ -224,7 +224,7 @@ final class JoglES2Renderer extends JoglES2Driver implements refexport_t, Ref {
     }
 
     public void screenshot() {
-        activateGLContext();
+        activateGLContext(true);
         impl.GL_ScreenShot_f();
     }
 
index ef5117b..3ff7ec6 100644 (file)
@@ -71,7 +71,7 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
         // pre init, reads Cvar's
         if (!impl.R_Init(vid_xpos, vid_ypos)) return false;
         // activates the OpenGL context        
-        activateGLContext();
+        activateGLContext(true);
         
         // post init        
         return impl.R_Init2();
@@ -88,7 +88,7 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#BeginRegistration(java.lang.String)
      */
     public final void BeginRegistration(String map) {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_BeginRegistration(map);
     }
 
@@ -96,7 +96,7 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterModel(java.lang.String)
      */
     public final model_t RegisterModel(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.R_RegisterModel(name);
     }
 
@@ -104,7 +104,7 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterSkin(java.lang.String)
      */
     public final image_t RegisterSkin(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.R_RegisterSkin(name);
     }
 
@@ -112,14 +112,14 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#RegisterPic(java.lang.String)
      */
     public final image_t RegisterPic(String name) {
-        activateGLContext();
+        activateGLContext(true);
         return impl.Draw_FindPic(name);
     }
     /** 
      * @see jake2.client.refexport_t#SetSky(java.lang.String, float, float[])
      */
     public final void SetSky(String name, float rotate, float[] axis) {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_SetSky(name, rotate, axis);
     }
 
@@ -127,7 +127,7 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#EndRegistration()
      */
     public final void EndRegistration() {
-        activateGLContext();
+        activateGLContext(true);
         impl.R_EndRegistration();
     }
 
@@ -163,7 +163,7 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
      * @see jake2.client.refexport_t#DrawChar(int, int, int)
      */
     public final void DrawChar(int x, int y, int num) {
-        activateGLContext();
+        activateGLContext(true);
         impl.Draw_Char(x, y, num);
     }
 
@@ -205,8 +205,8 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
     /** 
      * @see jake2.client.refexport_t#BeginFrame(float)
      */
-    public final void BeginFrame(float camera_separation) {
-        impl.R_BeginFrame(camera_separation);
+    public final boolean BeginFrame(float camera_separation) {
+        return impl.R_BeginFrame(camera_separation);
     }
 
     /** 
@@ -224,7 +224,7 @@ final class JoglGL2Renderer extends JoglGL2Driver implements refexport_t, Ref {
     }
 
     public void screenshot() {
-        activateGLContext();
+        activateGLContext(true);
         impl.GL_ScreenShot_f();
     }
 
index 0c5f9f1..8e75f2f 100644 (file)
@@ -48,7 +48,7 @@ public interface RenderAPI {
 
     void R_SetPalette(byte[] palette);
 
-    void R_BeginFrame(float camera_separation);
+    boolean R_BeginFrame(float camera_separation);
 
     void GL_ScreenShot_f();
 }
index 79bb86e..cc12a6c 100644 (file)
@@ -1358,7 +1358,7 @@ public abstract class Main extends Base {
        R_BeginFrame
        @@@@@@@@@@@@@@@@@@@@@
        */
-       public void R_BeginFrame(float camera_separation) {
+       public boolean R_BeginFrame(float camera_separation) {
            
            vid.update();
            
@@ -1408,7 +1408,7 @@ public abstract class Main extends Base {
                        }
                }
 
-        glImpl.beginFrame(camera_separation);
+            if( glImpl.beginFrame(camera_separation) ) {
 
                /*
                ** go into 2D mode
@@ -1466,6 +1466,11 @@ public abstract class Main extends Base {
                // clear screen if desired
                //
                R_Clear();
+               
+               return true;
+            } else {
+                return false;
+            }
        }
 
        int[] r_rawpalette = new int[256];
index 5459f20..13a31b3 100644 (file)
@@ -1312,7 +1312,7 @@ public abstract class Main extends Base {
     /**
      * R_BeginFrame
      */
-    public void R_BeginFrame(float camera_separation) {
+    public boolean R_BeginFrame(float camera_separation) {
 
         vid.update();
 
@@ -1363,64 +1363,68 @@ public abstract class Main extends Base {
             }
         }
 
-        glImpl.beginFrame(camera_separation);
-
-        /*
-         ** go into 2D mode
-         */
-        gl.glViewport(0, 0, vid.getWidth(), vid.getHeight());
-        gl.glMatrixMode(GL_PROJECTION);
-        gl.glLoadIdentity();
-        gl.glOrtho(0, vid.getWidth(), vid.getHeight(), 0, -99999, 99999);
-        gl.glMatrixMode(GL_MODELVIEW);
-        gl.glLoadIdentity();
-        gl.glDisable(GL_DEPTH_TEST);
-        gl.glDisable(GL_CULL_FACE);
-        gl.glDisable(GL_BLEND);
-        gl.glEnable(GL_ALPHA_TEST);
-        gl.glColor4f(1, 1, 1, 1);
-
-        /*
-         ** draw buffer stuff
-         */
-        if (gl_drawbuffer.modified) {
-            gl_drawbuffer.modified = false;
-
-            if (gl_state.camera_separation == 0 || !gl_state.stereo_enabled) {
-                if (gl_drawbuffer.string.equalsIgnoreCase("GL_FRONT"))
-                    gl.glDrawBuffer(GL_FRONT);
-                else
-                    gl.glDrawBuffer(GL_BACK);
+        if( glImpl.beginFrame(camera_separation) ) {
+            /*
+             ** go into 2D mode
+             */
+            gl.glViewport(0, 0, vid.getWidth(), vid.getHeight());
+            gl.glMatrixMode(GL_PROJECTION);
+            gl.glLoadIdentity();
+            gl.glOrtho(0, vid.getWidth(), vid.getHeight(), 0, -99999, 99999);
+            gl.glMatrixMode(GL_MODELVIEW);
+            gl.glLoadIdentity();
+            gl.glDisable(GL_DEPTH_TEST);
+            gl.glDisable(GL_CULL_FACE);
+            gl.glDisable(GL_BLEND);
+            gl.glEnable(GL_ALPHA_TEST);
+            gl.glColor4f(1, 1, 1, 1);
+    
+            /*
+             ** draw buffer stuff
+             */
+            if (gl_drawbuffer.modified) {
+                gl_drawbuffer.modified = false;
+    
+                if (gl_state.camera_separation == 0 || !gl_state.stereo_enabled) {
+                    if (gl_drawbuffer.string.equalsIgnoreCase("GL_FRONT"))
+                        gl.glDrawBuffer(GL_FRONT);
+                    else
+                        gl.glDrawBuffer(GL_BACK);
+                }
             }
+    
+            /*
+             ** texturemode stuff
+             */
+            if (gl_texturemode.modified) {
+                GL_TextureMode(gl_texturemode.string);
+                gl_texturemode.modified = false;
+            }
+    
+            if (gl_texturealphamode.modified) {
+                GL_TextureAlphaMode(gl_texturealphamode.string);
+                gl_texturealphamode.modified = false;
+            }
+    
+            if (gl_texturesolidmode.modified) {
+                GL_TextureSolidMode(gl_texturesolidmode.string);
+                gl_texturesolidmode.modified = false;
+            }
+    
+            /*
+             ** swapinterval stuff
+             */
+            GL_UpdateSwapInterval();
+    
+            //
+            // clear screen if desired
+            //
+            R_Clear();
+            
+            return true;
+        } else {
+            return true;
         }
-
-        /*
-         ** texturemode stuff
-         */
-        if (gl_texturemode.modified) {
-            GL_TextureMode(gl_texturemode.string);
-            gl_texturemode.modified = false;
-        }
-
-        if (gl_texturealphamode.modified) {
-            GL_TextureAlphaMode(gl_texturealphamode.string);
-            gl_texturealphamode.modified = false;
-        }
-
-        if (gl_texturesolidmode.modified) {
-            GL_TextureSolidMode(gl_texturesolidmode.string);
-            gl_texturesolidmode.modified = false;
-        }
-
-        /*
-         ** swapinterval stuff
-         */
-        GL_UpdateSwapInterval();
-
-        //
-        // clear screen if desired
-        //
-        R_Clear();
     }
 
     int[] r_rawpalette = new int[256];
index 7f86430..9d82593 100644 (file)
@@ -16,7 +16,8 @@ public interface GLDriver {
     
     void shutdown();
     
-    void beginFrame(float camera_separation);
+    /** @return true if successful, otherwise false. */
+    boolean beginFrame(float camera_separation);
     
     /** Performs <code>swapBuffers()</code>, ticks the fps counter and performs <code>QUIT</code> if requested. */ 
     void endFrame();
index e962c37..4ba98a0 100644 (file)
@@ -97,8 +97,9 @@ public abstract class JoglDummyDriver extends DummyGL implements GLDriver {
         return true;
     }
 
-    public void beginFrame(float camera_separation) {
-        activateGLContext();
+    @Override
+    public boolean beginFrame(float camera_separation) {
+        return activateGLContext(false);
     }
 
     public void endFrame() {
@@ -126,12 +127,12 @@ public abstract class JoglDummyDriver extends DummyGL implements GLDriver {
         callback.execute();
     }
 
-    protected final void activateGLContext() {
-        newtWin.activateGLContext();        
+    protected final boolean activateGLContext(boolean force) {
+        return newtWin.activateGLContext(false);        
     }
 
     protected final void deactivateGLContext() {
-        newtWin.activateGLContext();        
+        newtWin.deactivateGLContext();        
     }
     
     // --------------------------------------------------------------------------    
index 6f138cd..d798c72 100644 (file)
@@ -108,8 +108,9 @@ public abstract class JoglES1Driver extends JoglGL2ES1 implements GLDriver {
         return true;
     }
 
-    public void beginFrame(float camera_separation) {
-        newtWin.activateGLContext();
+    @Override
+    public boolean beginFrame(float camera_separation) {
+        return activateGLContext(false);
     }
 
     public void endFrame() {
@@ -136,12 +137,12 @@ public abstract class JoglES1Driver extends JoglGL2ES1 implements GLDriver {
         callback.execute();
     }
 
-    protected final void activateGLContext() {
-        newtWin.activateGLContext();        
+    protected final boolean activateGLContext(boolean force) {
+        return newtWin.activateGLContext(force);        
     }
 
     protected final void deactivateGLContext() {
-        newtWin.activateGLContext();        
+        newtWin.deactivateGLContext();        
     }
     
     // --------------------------------------------------------------------------    
index 08c95b9..f18a9cb 100644 (file)
@@ -113,8 +113,8 @@ public abstract class JoglES2Driver extends JoglGL2ES1 implements GLDriver {
         return true;
     }
 
-    public void beginFrame(float camera_separation) {
-        activateGLContext();
+    public boolean beginFrame(float camera_separation) {
+        return activateGLContext(false);
     }
 
     public void endFrame() {
@@ -141,12 +141,12 @@ public abstract class JoglES2Driver extends JoglGL2ES1 implements GLDriver {
         callback.execute();
     }
     
-    protected final void activateGLContext() {
-        newtWin.activateGLContext();        
+    protected final boolean activateGLContext(boolean force) {
+        return newtWin.activateGLContext(force);        
     }
 
     protected final void deactivateGLContext() {
-        newtWin.activateGLContext();        
+        newtWin.deactivateGLContext();        
     }
     
     // --------------------------------------------------------------------------    
index 0c95680..32195cb 100644 (file)
@@ -27,6 +27,7 @@ package jake2.render.opengl;
 
 import java.util.List;
 
+import jake2.client.VID;
 import jake2.game.cvar_t;
 import jake2.qcommon.Cvar;
 import jake2.qcommon.xcommand_t;
@@ -109,8 +110,9 @@ public abstract class JoglGL2Driver extends JoglGL2ES1 implements GLDriver {
         return true;
     }
 
-    public void beginFrame(float camera_separation) {
-        activateGLContext();
+    @Override
+    public boolean beginFrame(float camera_separation) {
+        return activateGLContext(false);
     }
 
     public void endFrame() {
@@ -137,12 +139,12 @@ public abstract class JoglGL2Driver extends JoglGL2ES1 implements GLDriver {
         callback.execute();
     }
 
-    protected final void activateGLContext() {
-        newtWin.activateGLContext();        
+    protected final boolean activateGLContext(boolean force) {
+        return newtWin.activateGLContext(force);        
     }
 
     protected final void deactivateGLContext() {
-        newtWin.activateGLContext();        
+        newtWin.deactivateGLContext();        
     }
     
     // --------------------------------------------------------------------------    
index ff7b949..df47bb1 100644 (file)
@@ -15,6 +15,7 @@ import jake2.qcommon.Cvar;
 import jake2.render.Base;
 import jake2.sys.NEWTKBD;
 
+import java.io.PrintStream;
 import java.util.List;
 
 import javax.media.nativewindow.CapabilitiesChooser;
@@ -22,26 +23,34 @@ import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
 import javax.media.nativewindow.util.Dimension;
 import javax.media.nativewindow.util.DimensionImmutable;
 import javax.media.nativewindow.util.SurfaceSize;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLProfile;
+import javax.media.opengl.*;
 
 import jogamp.opengl.FPSCounterImpl;
 
 import com.jogamp.common.os.Platform;
 import com.jogamp.newt.*;
-import com.jogamp.newt.event.WindowAdapter;
-import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.*;
 import com.jogamp.newt.opengl.GLWindow;
 import com.jogamp.newt.util.MonitorModeUtil;
 import com.jogamp.opengl.GenericGLCapabilitiesChooser;
 
 public class NEWTWin {
+    final static boolean DEBUG = false;
+    /** Required due to AWT lock of surface, if Applet! */
+    final static boolean FORCE_RELEASE_CTX_VAL = true; 
+    
     MonitorMode oldDisplayMode = null;
     volatile Screen screen = null;
     volatile GLWindow window = null;
+    volatile GameAnimatorControl animCtrl = null;
+    /** Encapsulateed AWT dependency */
+    volatile Object newtCanvasObject = null;
+    boolean forceReleaseCtx = false;
     volatile boolean shouldQuit = false;
-    final FPSCounterImpl fpsCounter = new FPSCounterImpl();
+    volatile boolean shouldPause = false;
+    volatile boolean shouldReparent = false;
+    volatile boolean isAnimating = false;
 
     public List<MonitorMode> getModeList() {
         if( null != window ) {
@@ -79,12 +88,10 @@ public class NEWTWin {
      * @param dim
      * @param mode
      * @param fullscreen
-     * @param driverName TODO
+     * @param driverName
      * @return enum Base.rserr_t
      */
     public int setMode(GLProfile glp, Dimension dim, int mode, boolean fullscreen, String driverName) {
-        final boolean isARM = Platform.CPUFamily.ARM == Platform.getCPUFamily();
-
         final Dimension newDim = new Dimension();
 
         VID.Printf(Defines.PRINT_ALL, "Initializing OpenGL display for profile "+glp+"\n");
@@ -120,7 +127,9 @@ public class NEWTWin {
                 chooser = new GenericGLCapabilitiesChooser(); // don't trust native GL-TK chooser
             }
         }
+        
         window = GLWindow.create(screen, caps);
+        window.setAutoSwapBufferMode(false);
         window.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); // we do handle QUIT on our own, no GLWindow.display() called.
         window.setCapabilitiesChooser(chooser);
         window.addWindowListener(new WindowAdapter() {
@@ -133,6 +142,9 @@ public class NEWTWin {
             }
         });
         window.setTitle("Jake2 ("+driverName+"-newt-"+glp.getName().toLowerCase()+")");
+        
+        animCtrl = new GameAnimatorControl();
+        window.setAnimator(animCtrl);
 
         final MonitorDevice mainMonitor = window.getMainMonitor();
         
@@ -146,88 +158,170 @@ public class NEWTWin {
         window.addWindowListener(NEWTKBD.listener);
         window.addKeyListener(NEWTKBD.listener);
         window.addMouseListener(NEWTKBD.listener);
-
-        if (fullscreen) {
-            MonitorMode mm = findDisplayMode(newDim);
-            final DimensionImmutable smDim = mm.getSurfaceSize().getResolution();
-            newDim.setWidth( smDim.getWidth() );
-            newDim.setHeight( smDim.getHeight() );
-            mainMonitor.setCurrentMode(mm);
-            window.setFullscreen(true);
-        } else {
-            window.setSize(newDim.getWidth(), newDim.getHeight());
-            if (Globals.appletMode) {
-                // Notify the size listener about the change
-                final SizeChangeListener listener = Globals.sizeChangeListener;
-                if (listener != null) {
-                    listener.sizeChanged(newDim.getWidth(), newDim.getHeight());
-                }
+        window.setSize(newDim.getWidth(), newDim.getHeight());
+        
+        isAnimating = true; // no display() invocation on other thread!
+                
+        if( !fullscreen && Globals.appletMode ) {
+            forceReleaseCtx = FORCE_RELEASE_CTX_VAL;
+            
+            // Notify the size listener about the change
+            final SizeChangeListener listener = Globals.sizeChangeListener;
+            if (listener != null) {
+                listener.sizeChanged(newDim.getWidth(), newDim.getHeight());
             }
-        }
-        window.setVisible(true);
-
-        if (!Globals.appletMode) {
-            while ( !window.isNativeValid()|| !window.isRealized() ) {
+            window.addKeyListener( new ReparentKeyListener() );
+            
+            final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(window);
+            final java.applet.Applet applet = (java.applet.Applet) Globals.applet;
+            final Runnable appletAddAction = new Runnable() {
+                public void run() {
+                    applet.add(newtCanvasAWT, java.awt.BorderLayout.CENTER);
+                    applet.validate();
+                    newtCanvasAWT.setFocusable(true);
+                    newtCanvasAWT.requestFocus();
+                    if( Platform.OSType.MACOS == Platform.getOSType() && newtCanvasAWT.isOffscreenLayerSurfaceEnabled() ) {
+                        System.err.println("XXX Relayout");
+                        // force relayout
+                        final int cW = newtCanvasAWT.getWidth();
+                        final int cH = newtCanvasAWT.getHeight();
+                        newtCanvasAWT.setSize(cW+1, cH+1);
+                        newtCanvasAWT.setSize(cW, cH);
+                    }
+                } };
+                if( java.awt.EventQueue.isDispatchThread() ) {
+                    System.err.println("XXX Adding on AWT EDT - same thread");
+                    appletAddAction.run();
+                } else {
+                    System.err.println("XXX Adding on AWT EDT - off thread");
+                    try {
+                        java.awt.EventQueue.invokeAndWait(appletAddAction);
+                    } catch (Exception e) {
+                        throw new RuntimeException("NEWT Exception during NewtCanvasAWT on AWT-EDT", e);
+                    }
+                }
+            newtCanvasObject = newtCanvasAWT;
+            int w=0;
+            while ( w<10 && !window.isNativeValid()|| !window.isRealized() ) {
+                w++;
                 try {
                     Thread.sleep(100);
                 } catch (InterruptedException e) {}
             }
+            System.err.println("XXX waited = "+w+" * 100 ms");
+        } else {
+            forceReleaseCtx = false;            
+            newtCanvasObject = null;
+            
+            if (fullscreen) {
+                MonitorMode mm = findDisplayMode(newDim);
+                final DimensionImmutable smDim = mm.getSurfaceSize().getResolution();
+                newDim.setWidth( smDim.getWidth() );
+                newDim.setHeight( smDim.getHeight() );
+                mainMonitor.setCurrentMode(mm);
+                VID.Printf(Defines.PRINT_ALL, "...MonitorMode "+mm+'\n');
+                window.setFullscreen(true);
+            }
+            
+            window.setVisible(true);
+            window.requestFocus();
+        }
+        if( !window.isNativeValid()|| !window.isRealized() ) {
+            throw new RuntimeException("NEWT window didn't not realize: "+window);
+        }
+        window.display(); // force GL creation
+        final GLContext ctx = window.getContext(); 
+        if( !ctx.isCreated() ) {
+            System.err.println("Warning: GL context not created: "+ctx);
+        }
+        if( ctx.isCurrent() ) {
+            throw new RuntimeException("NEWT GL context still current: "+ctx);
         }
-        window.requestFocus();
-        window.display(); // force GL resource validation
-        window.setAutoSwapBufferMode(false);
 
         VID.Printf(Defines.PRINT_ALL, "...reques GLCaps "+window.getRequestedCapabilities()+'\n');
         VID.Printf(Defines.PRINT_ALL, "...chosen GLCaps "+window.getChosenGLCapabilities()+'\n');
         VID.Printf(Defines.PRINT_ALL, "...size "+window.getWidth()+" x "+window.getHeight()+'\n');
-        fpsCounter.setUpdateFPSFrames(isARM ? 60 : 4*60, System.err);
 
         // propagateNewSize("init");
-        activateGLContext();
+        activateGLContext(true);
         
         return Base.rserr_ok;
     }
     
     private void propagateNewSize() {
-        final int width = window.getWidth();
-        final int height = window.getHeight();
-        final int _width;
-        final int mask = ~0x03;
-        if ((width & 0x03) != 0) {
-            _width = ( width & mask ) + 4;
-        } else {
-            _width = width;
+        if( null != window ) {
+            final int width = window.getWidth();
+            final int height = window.getHeight();
+            final int _width;
+            final int mask = ~0x03;
+            if ((width & 0x03) != 0) {
+                _width = ( width & mask ) + 4;
+            } else {
+                _width = width;
+            }
+            VID.Printf(Defines.PRINT_ALL, "Resize: " + width + " x " + height + ", masked " + _width + "x" + height + "\n");  
+    
+            Base.setVid(_width, height);
+            // let the sound and input subsystems know about the new window
+            VID.NewWindow(_width, height);
         }
-        VID.Printf(Defines.PRINT_ALL, "Resize: " + width + " x " + height + ", masked " + _width + "x" + height + "\n");  
-
-        Base.setVid(_width, height);
-        // let the sound and input subsystems know about the new window
-        VID.NewWindow(_width, height);                    
     }
 
-    protected final void activateGLContext() {
-        final GLContext ctx = window.getContext();
-        if ( null != ctx && GLContext.getCurrent() != ctx ) {                
-            ctx.makeCurrent();
+    protected final boolean activateGLContext(boolean force) {
+        boolean ctxCurrent = false;
+        if( force || !shouldPause ) {
+            final GLContext ctx = window.getContext();
+            if ( null != ctx && GLContext.getCurrent() != ctx ) {
+                if( DEBUG ) {
+                    System.err.println("GLCtx Current pause "+shouldPause+": "+Thread.currentThread().getName());
+                }
+                ctxCurrent = GLContext.CONTEXT_NOT_CURRENT < ctx.makeCurrent();
+            } else {
+                ctxCurrent = true;
+            }
+            isAnimating = ctxCurrent;
         }
+        return ctxCurrent;
     }
     
     protected final void deactivateGLContext() {
         final GLContext ctx = window.getContext();
         if ( null != ctx && GLContext.getCurrent() == ctx) {
+            if( DEBUG ) {
+                System.err.println("GLCtx Release pause "+shouldPause+": "+Thread.currentThread().getName());
+            }
             ctx.release();
         }        
     }
     
-    /** Performs {@link GLWindow#swapBuffers()}, ticks the fps counter and performs <code>QUIT</code> if requested. */
+    /** 
+     * Performs {@link GLWindow#swapBuffers()}, ticks the fps counter and performs <code>QUIT</code> if requested. 
+     */
     public final void endFrame() {
         window.swapBuffers();
-        fpsCounter.tickFPS();
+        animCtrl.fpsCounter.tickFPS();
         if( shouldQuit ) {
             deactivateGLContext();
             Cbuf.ExecuteText(Defines.EXEC_APPEND, "quit");
+        } else if( shouldReparent  ) {
+            shouldReparent  = false;
+            deactivateGLContext();
+            if( null != newtCanvasObject && null != window ) {
+                isAnimating = false; // don't let GLDrawableHelper.invoke(..) defer the GLRunnable (preserving GLState that is on OSX/CALayer) 
+                final NewtCanvasAWT newtCanvasAWT = (NewtCanvasAWT) newtCanvasObject;
+                if(null == window.getParent()) {
+                    forceReleaseCtx = FORCE_RELEASE_CTX_VAL; // Applet
+                    window.reparentWindow( newtCanvasAWT.getNativeWindow() );
+                } else {
+                    window.reparentWindow(null);
+                    forceReleaseCtx = false;
+                }
+            }            
+        } else if( forceReleaseCtx || shouldPause ) {
+            deactivateGLContext();
         }
     }
+    
     /** Performs <code>QUIT</code> if requested. */
     public final void checkQuit() {
         if( shouldQuit ) {
@@ -245,12 +339,174 @@ public class NEWTWin {
             deactivateGLContext();
             final GLWindow _window = window;
             window = null;
-            _window.destroy(); // same thing
+            _window.destroy();
+            if( null != Globals.applet && null != newtCanvasObject ) {
+                final java.applet.Applet applet = (java.applet.Applet) Globals.applet;
+                final NewtCanvasAWT newtCanvasAWT = (NewtCanvasAWT) newtCanvasObject;
+                final Runnable appletRemoveAction = new Runnable() {
+                    public void run() {
+                        applet.remove(newtCanvasAWT);
+                        applet.validate();
+                    } };
+                    if( java.awt.EventQueue.isDispatchThread() ) {
+                        appletRemoveAction.run();
+                    } else {
+                        try {
+                            java.awt.EventQueue.invokeAndWait(appletRemoveAction);
+                        } catch (Throwable e) {
+                            System.err.println("Catched "+e.getClass().getName()+": "+e.getMessage());
+                            e.printStackTrace();
+                        }
+                    }
+                newtCanvasAWT.setNEWTChild(null);
+                newtCanvasObject = null;
+            }
         }
         if( withScreen && null != screen ) {
-            screen.destroy();
+            try {
+                screen.destroy();
+            } catch (Throwable e) {
+                System.err.println("Catched "+e.getClass().getName()+": "+e.getMessage());
+                e.printStackTrace();
+            }
             screen = null;
         }
     }    
     
+    class GameAnimatorControl implements GLAnimatorControl {
+        final FPSCounterImpl fpsCounter;
+        final Thread thread;
+        
+        GameAnimatorControl() {
+            final boolean isARM = Platform.CPUFamily.ARM == Platform.getCPUFamily();
+            fpsCounter = new FPSCounterImpl();
+            fpsCounter.setUpdateFPSFrames(isARM ? 60 : 4*60, System.err);
+            thread = Thread.currentThread();
+        }
+        
+        @Override
+        public final boolean start() {
+            return false;
+        }
+
+        @Override
+        public final boolean stop() {
+            shouldQuit = true;
+            return true;
+        }
+
+        @Override
+        public final boolean pause() {
+            if( DEBUG ) {
+                System.err.println("GLCtx Pause Anim: "+Thread.currentThread().getName());
+                Thread.dumpStack();
+            }
+            shouldPause = true;
+            return true;
+        }
+
+        @Override
+        public final boolean resume() {
+            shouldPause = false;
+            return true;
+        }
+
+        @Override
+        public final boolean isStarted() {
+            return null != window;
+        }
+
+        @Override
+        public final boolean isAnimating() {
+            return isAnimating; // null != window && !shouldPause;
+        }
+
+        @Override
+        public final boolean isPaused() {
+            return null == window || shouldPause;
+        }
+
+        @Override
+        public final Thread getThread() {
+            return thread;
+        }
+        
+        @Override
+        public final void add(GLAutoDrawable drawable) {}
+
+        @Override
+        public final void remove(GLAutoDrawable drawable) {}
+        
+        @Override
+        public final void setUpdateFPSFrames(int frames, PrintStream out) {
+            fpsCounter.setUpdateFPSFrames(frames, out);
+        }
+
+        @Override
+        public final void resetFPSCounter() {
+            fpsCounter.resetFPSCounter();
+        }
+
+        @Override
+        public final int getUpdateFPSFrames() {
+            return fpsCounter.getUpdateFPSFrames();
+        }
+
+        @Override
+        public final long getFPSStartTime() {
+            return fpsCounter.getFPSStartTime();
+        }
+
+        @Override
+        public final long getLastFPSUpdateTime() {
+            return fpsCounter.getLastFPSUpdateTime();
+        }
+
+        @Override
+        public final long getLastFPSPeriod() {
+            return fpsCounter.getLastFPSPeriod();
+        }
+
+        @Override
+        public final float getLastFPS() {
+            return fpsCounter.getLastFPS();
+        }
+
+        @Override
+        public final int getTotalFPSFrames() {
+            return fpsCounter.getTotalFPSFrames();
+        }
+
+        @Override
+        public final long getTotalFPSDuration() {
+            return fpsCounter.getTotalFPSDuration();
+        }
+
+        @Override
+        public final float getTotalFPS() {
+            return fpsCounter.getTotalFPS();
+        }
+    }
+    
+    class ReparentKeyListener implements KeyListener {
+        @Override
+        public void keyPressed(KeyEvent e) {
+           System.err.println(e);
+           if( !e.isAutoRepeat() ) {
+               int keyCode = e.getKeyCode();
+               // FIXME: Workaround JOGL/NEWT Bug 798
+               if( 0 == keyCode ) {
+                   keyCode = e.getKeySymbol();
+               }
+               if( KeyEvent.VK_HOME == keyCode ) {
+                   shouldReparent = true;
+               }
+           }
+        }
+        @Override
+        public void keyReleased(KeyEvent e) { 
+            System.err.println(e);
+        }
+    }
+    
 }
index bff13d5..0b55f52 100644 (file)
@@ -44,21 +44,25 @@ public final class InputListener implements KeyListener, MouseListener, WindowLi
        }
 
        static Jake2InputEvent nextEvent() {
-               Jake2InputEvent ev;
-               synchronized (eventQueue) {
-                       ev = (!eventQueue.isEmpty())?(Jake2InputEvent)eventQueue.removeFirst():null;
-               }
-               return ev;
+               Jake2InputEvent ev;
+               synchronized (eventQueue) {
+                       ev = (!eventQueue.isEmpty())?(Jake2InputEvent)eventQueue.removeFirst():null;
+               }
+               return ev;
        }
 
         @Override
        public void keyPressed(KeyEvent e) {
-           addEvent(new Jake2InputEvent(Jake2InputEvent.KeyPress, e));
+            if( !e.isAutoRepeat() ) {
+                addEvent(new Jake2InputEvent(Jake2InputEvent.KeyPress, e));
+            }
        }
 
         @Override
        public void keyReleased(KeyEvent e) {
-           addEvent(new Jake2InputEvent(Jake2InputEvent.KeyRelease, e));
+            if( !e.isAutoRepeat() ) {
+                addEvent(new Jake2InputEvent(Jake2InputEvent.KeyRelease, e));
+            }
        }
 
         @Override
index 4a0ba76..af54a36 100644 (file)
@@ -119,6 +119,10 @@ final public class NEWTKBD extends KBD
 
        private static int XLateKeyCode(KeyEvent ev) { 
                int code = ev.getKeyCode();
+               // FIXME: Workaround JOGL/NEWT Bug 798
+               if( 0 == code ) {
+                   code = ev.getKeySymbol();
+               }
                 int key = 0;
                switch(code) {
 //     00626                 case XK_KP_Page_Up:      key = K_KP_PGUP; break;
index 8ac8fb1..cefb303 100644 (file)
@@ -226,7 +226,7 @@ public final class Sys extends Defines {
     }
 
     public static void SendKeyEvents() {
-               Globals.re.getKeyboardHandler().Update();
+        Globals.re.getKeyboardHandler().Update();
 
         // grab frame time
         Globals.sys_frame_time = Timer.Milliseconds();
diff --git a/webstart/jake2-napplet01.html b/webstart/jake2-napplet01.html
new file mode 100644 (file)
index 0000000..9279c79
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>Jake2 NEWT NApplet 01</title>
+</head>
+<body  bgcolor="#333333" text="#BBBBBB">
+
+<P>
+Jake2 NApplet
+<ul>
+    <li> ESC - release the game mouse grab.</li>
+    <li> HOME - in/out browser window. </li>
+    <li> Video Mode Size change will change the Applet size.</li>
+    <li> Fullscreen will bring the window out of the browser as well
+         and MonitorMode is applied to the main MonitorDevice.</li>
+</ul>
+Bugs:
+<ul>
+    <li>OSX: Fullscreen may freeze the JVM/Desktop, due to CGL.setContextView() deadlock</li>
+</ul>
+</P>
+
+<P>
+<object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
+      width="50%" height="45%">
+   <param name="id" value="Jake2">
+   <param name="code" value="jake2.Jake2Applet">
+   <param name="archive" value="http://jogamp.org/deployment/jogamp-current/jar/gluegen-rt.jar,
+                                http://jogamp.org/deployment/jogamp-current/jar/jogl-all.jar,
+                                http://jogamp.org/deployment/jogamp-current/jar/joal.jar,
+                                jar/jake2.jar">
+   <param name="java_arguments" value="-Dsun.java2d.noddraw=true">
+   <param name="jake_args" value="+set vid_ref joglgl2 +set s_impl joal +set adr0 jake2.in-chemnitz.de">
+   <comment>
+     <embed id="Jake2" code="jake2.Jake2Applet"
+          width="50%" height="45%"
+          type="application/x-java-applet;version=1.6"
+          pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
+          archive="http://jogamp.org/deployment/jogamp-current/jar/gluegen-rt.jar,
+                   http://jogamp.org/deployment/jogamp-current/jar/jogl-all.jar,
+                    http://jogamp.org/deployment/jogamp-current/jar/joal.jar,
+                   jar/jake2.jar"
+          java_arguments="-Dsun.java2d.noddraw=true"
+          jake_args="+set vid_ref joglgl2 +set s_impl joal +set adr0 jake2.in-chemnitz.de">
+        <noembed>Sorry, no Java support detected.</noembed>
+     </embed>
+   </comment>
+</object>
+
+</P>
+
+</body>
+</html>
diff --git a/webstart/jake2-napplet01_dbg.html b/webstart/jake2-napplet01_dbg.html
new file mode 100644 (file)
index 0000000..f7c6086
--- /dev/null
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>Jake2 NEWT NApplet 01</title>
+</head>
+<body  bgcolor="#333333" text="#BBBBBB">
+
+Jake2 NApplet Debug Mode
+
+<P>
+<object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
+      width="50%" height="45%">
+   <param name="id" value="Jake2">
+   <param name="code" value="jake2.Jake2Applet">
+   <param name="archive" value="http://jogamp.org/deployment/jogamp-current/jar/gluegen-rt.jar,
+                                http://jogamp.org/deployment/jogamp-current/jar/jogl-all.jar,
+                                http://jogamp.org/deployment/jogamp-current/jar/joal.jar,
+                                jar/jake2.jar">
+   <param name="java_arguments" value="-Dsun.java2d.noddraw=true -Djnlp.newt.debug.Window -Djnlp.jogamp.debug.Lock -Djnlp.jogl.debug=all">
+   <param name="jake_args" value="+set vid_ref joglgl2 +set s_impl joal +set adr0 jake2.in-chemnitz.de">
+   <comment>
+     <embed id="Jake2" code="jake2.Jake2Applet"
+          width="50%" height="45%"
+          type="application/x-java-applet;version=1.6"
+          pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
+          archive="http://jogamp.org/deployment/jogamp-current/jar/gluegen-rt.jar,
+                   http://jogamp.org/deployment/jogamp-current/jar/jogl-all.jar,
+                    http://jogamp.org/deployment/jogamp-current/jar/joal.jar,
+                   jar/jake2.jar"
+          java_arguments="-Dsun.java2d.noddraw=true -Djnlp.newt.debug.Window -Djnlp.jogamp.debug.Lock -Djnlp.jogl.debug=all"
+          jake_args="+set vid_ref joglgl2 +set s_impl joal +set adr0 jake2.in-chemnitz.de">
+        <noembed>Sorry, no Java support detected.</noembed>
+     </embed>
+   </comment>
+</object>
+
+</P>
+
+</body>
+</html>
index 4be2496..14fdd7e 100644 (file)
@@ -38,7 +38,7 @@
                <argument>clientport</argument>
                <argument>27910</argument>
                <argument>+connect</argument>
-               <argument>88.198.147.212</argument>                                     
+               <argument>88.198.147.212</argument>
        </application-desc> 
        
 </jnlp>
http://JogAmp.org git info: FAQ, tutorial and man pages.