diff options
author | Sven Gothel <[email protected]> | 2013-03-22 13:43:59 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-03-22 13:43:59 +0100 |
commit | d514ecbf052d013ea8c0982c490757678075a9ea (patch) | |
tree | 4870bf7ecb093e8327e06a13caf65127586ddba0 /src/newt | |
parent | 3673964caf2c4ac4efddffb8d7e9c28cce49b48c (diff) |
NEWT/Android (Bug 665): Add Support for GLStateKeeper ; onPause() always destroys ; Recognizing all GLAutoDrawable's GLAnimatorControl for pause/resume ; Use GLAnimatorControl instead of Animator
- Add Support for GLStateKeeper
If !isFinishing() (HOME button), preserve the GLEventListener if an GLStateKeeper instance
- onPause() always destroys
onDestroy() is too late, i.e. surfaceDestroyed() already called
- Recognizing all GLAutoDrawable's GLAnimatorControl for pause/resume
pause/resume the GLAnimatorControl of all GLAutoDrawable instances
- Use GLAnimatorControl instead of Animator
We used an Animator reference .. duh!
Note: The EGL native WindowDriver (Android and BCM.IV) must retain their own copy of EGLGraphicsDevice,
which preserves the EGLDisplay handle due to EGLDisplayUtil reference counting per nativeHandleID.
Diffstat (limited to 'src/newt')
4 files changed, 165 insertions, 52 deletions
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java index 726793768..2ea7a9d84 100644 --- a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java +++ b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java @@ -32,9 +32,12 @@ import java.util.List; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.opengl.FPSCounter; +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; import com.jogamp.newt.Window; -import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.GLStateKeeper; import jogamp.newt.driver.android.WindowDriver; @@ -46,12 +49,46 @@ import android.view.WindowManager; public class NewtBaseActivity extends Activity { List<Window> newtWindows = new ArrayList<Window>(); - Animator animator = null; + List<GLAutoDrawable> glAutoDrawables = new ArrayList<GLAutoDrawable>(); + + GLAnimatorControl animator = null; boolean isDelegatedActivity; Activity rootActivity; boolean setThemeCalled = false; + protected void startAnimation(boolean start) { + if(null != animator) { + final boolean res; + if( start ) { + if( animator.isPaused() ) { + res = animator.resume(); + } else { + res = animator.start(); + } + } else { + res = animator.stop(); + } + Log.d(MD.TAG, "Animator global: start "+start+", result "+res); + } + for(int i=0; i<glAutoDrawables.size(); i++) { + final GLAnimatorControl anim = glAutoDrawables.get(i).getAnimator(); + if(null != anim) { + final boolean res; + if( start ) { + if( anim.isPaused() ) { + res = anim.resume(); + } else { + res = anim.start(); + } + } else { + res = anim.stop(); + } + Log.d(MD.TAG, "Animator glad["+i+"]: start "+start+", result "+res); + } + } + } + public NewtBaseActivity() { super(); isDelegatedActivity = false; @@ -79,19 +116,21 @@ public class NewtBaseActivity extends Activity { * </p> * @param androidWindow * @param newtWindow + * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver. + * @see #registerNEWTWindow(Window) * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams) */ - public void setContentView(android.view.Window androidWindow, Window newtWindow) { - newtWindow = newtWindow.getDelegatedWindow(); - if(newtWindow instanceof WindowDriver) { - adaptTheme4Transparency(newtWindow.getRequestedCapabilities()); - layoutForNEWTWindow(androidWindow, newtWindow); - WindowDriver newtAWindow = (WindowDriver)newtWindow; + public void setContentView(final android.view.Window androidWindow, final Window newtWindow) throws IllegalArgumentException { + final Window delegateWindow = newtWindow.getDelegatedWindow(); + if(delegateWindow instanceof WindowDriver) { + adaptTheme4Transparency(delegateWindow.getRequestedCapabilities()); + layoutForNEWTWindow(androidWindow, delegateWindow); + final WindowDriver newtAWindow = (WindowDriver)delegateWindow; androidWindow.setContentView(newtAWindow.getAndroidView()); - registerNEWTWindow(newtAWindow); } else { - throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass()); + throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass().getName()); } + registerNEWTWindow(newtWindow); } /** * This is one of the three registration methods (see below). @@ -102,35 +141,67 @@ public class NewtBaseActivity extends Activity { * @param androidWindow * @param newtWindow * @param params - * @see #setContentView(android.view.Window, Window) + * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver. * @see #registerNEWTWindow(Window) + * @see #setContentView(android.view.Window, Window) */ - public void addContentView(android.view.Window androidWindow, Window newtWindow, android.view.ViewGroup.LayoutParams params) { - newtWindow = newtWindow.getDelegatedWindow(); - if(newtWindow instanceof WindowDriver) { - WindowDriver newtAWindow = (WindowDriver)newtWindow; + public void addContentView(final android.view.Window androidWindow, final Window newtWindow, final android.view.ViewGroup.LayoutParams params) throws IllegalArgumentException { + final Window delegateWindow = newtWindow.getDelegatedWindow(); + if(delegateWindow instanceof WindowDriver) { + final WindowDriver newtAWindow = (WindowDriver)delegateWindow; androidWindow.addContentView(newtAWindow.getAndroidView(), params); - registerNEWTWindow(newtAWindow); } else { - throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass()); + throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName()); } + registerNEWTWindow(newtWindow); } /** * This is one of the three registration methods (see below). * <p> - * This methods simply registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}. - * </p> + * This methods registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}. + * </p> + * <p> + * If adding a {@link GLAutoDrawable} implementation, the {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()} + * will be used for {@link #onPause()} and {@link #onResume()}. + * </p> + * <p> + * If adding a {@link GLAutoDrawable} implementation, the {@link GLEventListenerState} will preserve it's state + * when {@link #onPause()} is being called while not {@link #isFinishing()}. A later {@link #onResume()} will + * reinstate the {@link GLEventListenerState}. + * </p> * * @param newtWindow + * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver. * @see #setContentView(android.view.Window, Window) * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams) */ - public void registerNEWTWindow(Window newtWindow) { - newtWindow = newtWindow.getDelegatedWindow(); - WindowDriver newtAWindow = (WindowDriver)newtWindow; - newtAWindow.registerActivity(getActivity()); + public void registerNEWTWindow(final Window newtWindow) throws IllegalArgumentException { + final Window delegateWindow = newtWindow.getDelegatedWindow(); + Log.d(MD.TAG, "registerNEWTWindow: Type "+newtWindow.getClass().getName()+", delegate "+delegateWindow.getClass().getName()); + if(delegateWindow instanceof WindowDriver) { + final WindowDriver newtAWindow = (WindowDriver)delegateWindow; + newtAWindow.registerActivity(getActivity()); + } else { + throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName()); + } newtWindows.add(newtWindow); + if(newtWindow instanceof GLAutoDrawable) { + glAutoDrawables.add((GLAutoDrawable)newtWindow); + } + if(newtWindow instanceof GLStateKeeper) { + ((GLStateKeeper)newtWindow).setGLStateKeeperListener(glStateKeeperListener); + } } + private final GLStateKeeper.Listener glStateKeeperListener = new GLStateKeeper.Listener() { + @Override + public void glStatePreserveNotify(GLStateKeeper glsk) { + Log.d(MD.TAG, "GLStateKeeper Preserving: 0x"+Integer.toHexString(glsk.hashCode())); + } + @Override + public void glStateRestored(GLStateKeeper glsk) { + Log.d(MD.TAG, "GLStateKeeper Restored: 0x"+Integer.toHexString(glsk.hashCode())); + } + }; /** * Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window. @@ -224,7 +295,19 @@ public class NewtBaseActivity extends Activity { } } - public void setAnimator(Animator animator) { + /** + * Setting up a global {@Link GLAnimatorControl} for {@link #onPause()} and {@link #onResume()}. + * <p> + * Note that if adding a {@link GLAutoDrawable} implementation via {@link #registerNEWTWindow(Window)}, + * {@link #setContentView(android.view.Window, Window)} or {@link #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)} + * their {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()} will be used as well. + * In this case, using this global {@Link GLAnimatorControl} is redundant. + * </p> + * @see #registerNEWTWindow(Window) + * @see #setContentView(android.view.Window, Window) + * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams) + */ + public void setAnimator(GLAnimatorControl animator) { this.animator = animator; if(!animator.isStarted()) { animator.start(); @@ -279,23 +362,33 @@ public class NewtBaseActivity extends Activity { ((FPSCounter)win).resetFPSCounter(); } } - if(null != animator) { - animator.resume(); - animator.resetFPSCounter(); - } + startAnimation(true); } @Override public void onPause() { Log.d(MD.TAG, "onPause"); - if(null != animator) { - animator.pause(); + if( !getActivity().isFinishing() ) { + int ok=0, fail=0; + for(int i=0; i<glAutoDrawables.size(); i++) { + final GLAutoDrawable glad = glAutoDrawables.get(i); + if(glad instanceof GLStateKeeper) { + if( ((GLStateKeeper)glad).preserveGLStateAtDestroy(true) ) { + ok++; + } else { + fail++; + } + } + } + Log.d(MD.TAG, "GLStateKeeper.Preserving: Total "+glAutoDrawables.size()+", OK "+ok+", Fail "+fail); } for(int i=0; i<newtWindows.size(); i++) { final Window win = newtWindows.get(i); win.setVisible(false); + win.destroy(); } - if(!isDelegatedActivity()) { + startAnimation(false); + if( !isDelegatedActivity() ) { super.onPause(); } } @@ -303,7 +396,7 @@ public class NewtBaseActivity extends Activity { @Override public void onStop() { Log.d(MD.TAG, "onStop"); - if(!isDelegatedActivity()) { + if( !isDelegatedActivity() ) { super.onStop(); } } @@ -311,14 +404,8 @@ public class NewtBaseActivity extends Activity { @Override public void onDestroy() { Log.d(MD.TAG, "onDestroy"); - if(null != animator) { - animator.stop(); - animator = null; - } - while(newtWindows.size()>0) { - final Window win = newtWindows.remove(newtWindows.size()-1); - win.destroy(); - } + newtWindows.clear(); + glAutoDrawables.clear(); jogamp.common.os.android.StaticContext.clear(); if(!isDelegatedActivity()) { super.onDestroy(); diff --git a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java index 795aac5fb..aee372f01 100644 --- a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java @@ -28,19 +28,19 @@ package jogamp.newt.driver.android; -import javax.media.nativewindow.*; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.util.Dimension; import javax.media.nativewindow.util.Point; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.ScreenModeUtil; - import android.content.Context; import android.graphics.PixelFormat; import android.util.DisplayMetrics; import android.view.Surface; import android.view.WindowManager; +import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.util.ScreenModeUtil; + public class ScreenDriver extends jogamp.newt.ScreenImpl { static { diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java index 8f9ee1c0f..6f78a6f6b 100644 --- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -33,8 +33,10 @@ import jogamp.newt.WindowImpl; import jogamp.newt.driver.android.event.AndroidNewtEventFactory; import jogamp.newt.driver.android.event.AndroidNewtEventTranslator; +import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.Capabilities; import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; @@ -49,6 +51,7 @@ import com.jogamp.newt.Screen; import com.jogamp.newt.ScreenMode; import jogamp.opengl.egl.EGL; +import jogamp.opengl.egl.EGLDisplayUtil; import jogamp.opengl.egl.EGLGraphicsConfiguration; import jogamp.opengl.egl.EGLGraphicsConfigurationFactory; @@ -322,7 +325,14 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { @Override protected final void createNativeImpl() { - Log.d(MD.TAG, "createNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ + // Create own screen/device resource instance allowing independent ownership, + // while still utilizing shared EGL resources. + final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + final EGLGraphicsDevice aDevice = (EGLGraphicsDevice) aScreen.getDevice(); + final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(aDevice.getNativeDisplayID(), aDevice.getConnection(), aDevice.getUnitID()); + final DefaultGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aScreen.getIndex()); + + Log.d(MD.TAG, "createNativeImpl 0 - eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - on thread "+Thread.currentThread().getName()); if(0!=getParentWindowHandle()) { @@ -332,11 +342,9 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { throw new InternalError("surfaceHandle null"); } - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice(); final EGLGraphicsConfiguration eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(), - (GLCapabilitiesChooser)capabilitiesChooser, getScreen().getGraphicsScreen(), nativeFormat, - isAndroidFormatTransparent(androidFormat)); + (GLCapabilitiesChooser)capabilitiesChooser, eglScreen, nativeFormat, isAndroidFormatTransparent(androidFormat)); if (eglConfig == null) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } @@ -361,12 +369,14 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { setupInputListener(true); - Log.d(MD.TAG, "createNativeImpl X: eglSurfaceHandle 0x"+Long.toHexString(eglSurface)); + Log.d(MD.TAG, "createNativeImpl X: eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", eglSurfaceHandle 0x"+Long.toHexString(eglSurface)); } @Override protected final void closeNativeImpl() { - Log.d(MD.TAG, "closeNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getGraphicsConfiguration().getScreen().getDevice(); + + Log.d(MD.TAG, "closeNativeImpl 0 - eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ ", eglSurfaceHandle 0x"+Long.toHexString(eglSurface)+ ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - on thread "+Thread.currentThread().getName()); if(WindowImpl.DEBUG_IMPLEMENTATION) { @@ -377,7 +387,6 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { if(0 != eglSurface) { try { - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice(); if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) { throw new GLException("Error destroying window surface (eglDestroySurface)"); } @@ -389,6 +398,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { } } release0(surfaceHandle); + + eglDevice.close(); if( null != androidView ) { if( added2StaticViewGroup ) { diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java index bdef8e6cd..e820439d0 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java @@ -29,16 +29,21 @@ package jogamp.newt.driver.bcm.vc.iv; import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.Capabilities; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + import jogamp.newt.WindowImpl; import jogamp.newt.driver.linux.LinuxEventDeviceTracker; import jogamp.newt.driver.linux.LinuxMouseTracker; +import jogamp.opengl.egl.EGLDisplayUtil; public class WindowDriver extends WindowImpl { private static final String WINDOW_CLASS_NAME = "NewtWindow"; @@ -54,9 +59,15 @@ public class WindowDriver extends WindowImpl { if(0!=getParentWindowHandle()) { throw new RuntimeException("Window parenting not supported (yet)"); } + // Create own screen/device resource instance allowing independent ownership, + // while still utilizing shared EGL resources. + final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + final EGLGraphicsDevice aDevice = (EGLGraphicsDevice) aScreen.getDevice(); + final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(aDevice.getNativeDisplayID(), aDevice.getConnection(), aDevice.getUnitID()); + final DefaultGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aScreen.getIndex()); final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); + capsRequested, capsRequested, capabilitiesChooser, eglScreen, VisualIDHolder.VID_UNDEFINED); if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } @@ -82,6 +93,8 @@ public class WindowDriver extends WindowImpl { } protected void closeNativeImpl() { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getGraphicsConfiguration().getScreen().getDevice(); + removeWindowListener(LinuxMouseTracker.getSingleton()); removeWindowListener(LinuxEventDeviceTracker.getSingleton()); @@ -89,6 +102,8 @@ public class WindowDriver extends WindowImpl { CloseWindow(windowHandleClose, windowUserData); windowUserData=0; } + + eglDevice.close(); } protected void requestFocusImpl(boolean reparented) { |