Pausing the OpenGL Surface


#1

First, a bit of logic missing from the Activity. onPause' should call theonPause’ method of the OGL surface.

[code]— w:\sw\juce\modules\juce_core\native\java\JuceAppActivity.java 2012-12-21 16:57:25.000000000 -0000
+++ c:\sw\juce\modules\juce_core\native\java\JuceAppActivity.java 2013-01-07 21:33:25.000000000 -0000
@@ -78,35 +89,48 @@
super.onDestroy();
}

 @Override
 protected final void onPause()
 {
  •    viewHolder.onPause();
       suspendApp();
       super.onPause();
    

    }

    @Override
    protected final void onResume()
    {
    super.onResume();

  •    viewHolder.onResume();
       resumeApp();
    

    }

    @Override
    public void onConfigurationChanged (Configuration cfg)
    {
    super.onConfigurationChanged (cfg);
    setContentView (viewHolder);
    }

    private void callAppLauncher()
    {
    launchApp (getApplicationInfo().publicSourceDir,
    getApplicationInfo().dataDir);
    }

    //==============================================================================
    private native void launchApp (String appFile, String appDataDir);
    private native void quitApp();
    private native void suspendApp();
    private native void resumeApp();
    @@ -161,12 +185,40 @@
    setScreenSize (getWidth(), getHeight());

           if (isFirstResize)
           {
               isFirstResize = false;
               callAppLauncher();
    
  •        }
    
  •    }
    
  •    public final void onPause()
    
  •    {
    
  •        int n = getChildCount();
    
  •        for (int i = 0; i < n; ++i)
    
  •        {
    
  •            View v = getChildAt(i);
    
  •            if (v instanceof ComponentPeerView)
    
  •            {
    
  •                ComponentPeerView pv = (ComponentPeerView)v;
    
  •                pv.onPause();
    
  •            }
    
  •        }
    
  •    }
    
  •    public final void onResume()
    
  •    {
    
  •        int n = getChildCount();
    
  •        for (int i = 0; i < n; ++i)
    
  •        {
    
  •            View v = getChildAt(i);
    
  •            if (v instanceof ComponentPeerView)
    
  •            {
    
  •                ComponentPeerView pv = (ComponentPeerView)v;
    
  •                pv.onResume();
    
  •            }
           }
       }
    
       private boolean isFirstResize = true;
    

    }

@@ -434,30 +479,64 @@

     public boolean containsPoint (int x, int y)
     {
         return true; //xxx needs to check overlapping views
     }
  •    OpenGLView glView;
    
  •    public final void onPause()
    
  •    {
    
  •        if (glView != null)
    
  •            glView.onPause();
    
  •    }
    
  •    public final void onResume()
    
  •    {
    
  •        if (glView != null)
    
  •            glView.onResume();
    
  •    }
    
  •    public OpenGLView createGLView()
       {
    
  •        OpenGLView glView = new OpenGLView (getContext());
    
  •        glView = new OpenGLView (getContext());
           addView (glView);
           return glView;
       }
    

    }

    //==============================================================================
    public final class OpenGLView extends GLSurfaceView
    implements GLSurfaceView.Renderer
    {
    OpenGLView (Context context)
    {
    super (context);
    setEGLContextClientVersion (2);
    setRenderer (this);
    setRenderMode (RENDERMODE_WHEN_DIRTY);
    }

       @Override
       public void onSurfaceCreated (GL10 unused, EGLConfig config)
       {
           contextCreated();
    

[/code]

Then there is an additional problem with the MessageManagerLock.

With the above onPause' changes, an app can be paused and resumed providing it is only rendering 3D. However, if we are also callingpaint’ in the same component, the MM lock is taken.

When `onPause’ is encountered, somehow the lock is often being held whilst suspended, whence resume cannot issue any events and deadlock occurs. Sometimes you have to kill the app with the task manager it’s that bad.

I’ve been looking for a way to fix this. maybe the suspendApp' call should, beforesuspended’ is called, issue a signal to the opengl thread to stop rather than letting Android do it. I don’t know when android is actually doing this. Perhaps it (ie the suspend) can happen at any OGL system call.


#2

I put this is, but it didn’t compile (?) so I’ve rolled it back again… Not sure what to suggest, but let me know if you figure out a plan for this.


#3

looks like i messed up the diff?

What’s going on is i propagate the activity onPause' andonResume’ to the OpenGLView. What this does is suspend OGL activity when paused. I think it could be implemented a bit simpler than my, rather roundabout, way.


#4

Sorry, I think I might have messed something in my first attempt.

Anyway, I’ve had another go. I had to change it a bit because you were assuming that only one OpenGLView would be created, and that might not be the case, so let me know if my version works for you.