Android: Added first prototype of AndroidAudioRenderer

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7723 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
kim..ng 14 years ago
parent 68bac95cd5
commit a7974ac659
  1. 15
      engine/src/android/com/jme3/app/AndroidHarness.java
  2. 4
      engine/src/android/com/jme3/asset/AndroidAssetManager.java
  3. 54
      engine/src/android/com/jme3/audio/android/AndroidAudioData.java
  4. 518
      engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java
  5. 27
      engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java
  6. 40
      engine/src/android/com/jme3/system/JmeSystem.java
  7. 58
      engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
  8. 48
      engine/src/android/com/jme3/system/android/OGLESContext.java

@ -46,6 +46,11 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
* ConfigType.BEST is RGBA8888 or better if supported by the hardware
*/
protected ConfigType eglConfigType = ConfigType.FASTEST;
/**
* If true all valid and not valid egl configs are logged
*/
protected boolean eglConfigVerboseLogging = false;
/**
* Title of the exit dialog, default is "Do you want to exit?"
@ -68,6 +73,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
super.onCreate(savedInstanceState);
JmeSystem.setResources(getResources());
JmeSystem.setActivity(this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
@ -88,7 +94,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
app.setSettings(settings);
app.start();
ctx = (OGLESContext) app.getContext();
view = ctx.createView(input, eglConfigType);
view = ctx.createView(input, eglConfigType, eglConfigVerboseLogging);
setContentView(view);
}
@ -129,8 +135,8 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
@Override
protected void onDestroy(){
super.onDestroy();
app.stop();
app.stop(true);
super.onDestroy();
logger.info("onDestroy");
}
@ -138,6 +144,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
{
return app;
}
/**
* Called when an error has occured. This is typically
* invoked when an uncought exception is thrown in the render thread.
@ -186,7 +193,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
{
if (whichButton != -2)
{
app.stop();
app.stop(true);
this.finish();
}
}

@ -39,6 +39,7 @@ import java.util.logging.Logger;
import com.jme3.asset.plugins.AndroidLocator;
import com.jme3.asset.plugins.ClasspathLocator;
import com.jme3.audio.plugins.AndroidAudioLoader;
/**
* <code>AndroidAssetManager</code> is an implementation of DesktopAssetManager for Android
@ -72,7 +73,8 @@ public class AndroidAssetManager extends DesktopAssetManager {
// Set Default Android config
this.registerLocator("", AndroidLocator.class);
this.registerLocator("", ClasspathLocator.class);
this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");
this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");
this.registerLoader(AndroidAudioLoader.class, "ogg", "mp3");
this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m");
this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md");
this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt");

@ -0,0 +1,54 @@
package com.jme3.audio.android;
import com.jme3.asset.AssetKey;
import com.jme3.audio.AudioData;
import com.jme3.audio.AudioRenderer;
public class AndroidAudioData extends AudioData
{
protected AssetKey assetKey;
protected int soundId = 0;
public AssetKey getAssetKey() {
return assetKey;
}
public void setAssetKey(AssetKey assetKey) {
this.assetKey = assetKey;
}
public int getSoundId() {
return soundId;
}
public void setSoundId(int soundId) {
this.soundId = soundId;
}
@Override
public DataType getDataType() {
// TODO Auto-generated method stub
return null;
}
@Override
public float getDuration() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void resetObject() {
// TODO Auto-generated method stub
}
@Override
public void deleteObject(AudioRenderer r) {
// TODO Auto-generated method stub
}
}

@ -0,0 +1,518 @@
/*
* Copyright (c) 2009-2010 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.audio.android;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.media.AudioManager;
import android.media.SoundPool;
import com.jme3.audio.ListenerParam;
import com.jme3.audio.AudioParam;
import com.jme3.audio.AudioBuffer;
import com.jme3.audio.AudioData;
import com.jme3.audio.AudioRenderer;
import com.jme3.audio.AudioNode;
import com.jme3.audio.AudioNode.Status;
import com.jme3.audio.AudioStream;
import com.jme3.audio.Environment;
import com.jme3.audio.Filter;
import com.jme3.audio.Listener;
import com.jme3.audio.LowPassFilter;
import com.jme3.math.Vector3f;
import com.jme3.util.BufferUtils;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class is the android implementation for {@link AudioRenderer}
* @author larynx
*
*/
public class AndroidAudioRenderer implements AudioRenderer, SoundPool.OnLoadCompleteListener
{
private static final Logger logger = Logger.getLogger(AndroidAudioRenderer.class.getName());
private final static int MAX_NUM_CHANNELS = 16;
private SoundPool soundPool = null;
private final AudioManager manager;
private final Context context;
private final AssetManager am;
private HashMap<Integer, AudioNode> mapLoadingAudioNodes = new HashMap<Integer, AudioNode>();
private final AtomicBoolean lastLoadCompleted = new AtomicBoolean();
private Listener listener;
private boolean audioDisabled = false;
public AndroidAudioRenderer(Activity context)
{
this.context = context;
manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
am = context.getAssets();
}
@Override
public void initialize()
{
soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(this);
}
private void updateFilter(Filter f)
{
throw new UnsupportedOperationException("Filter type unsupported: " + f.getClass().getName());
}
@Override
public void updateSourceParam(AudioNode src, AudioParam param)
{
if (audioDisabled)
return;
if (src.getChannel() < 0)
return;
assert src.getChannel() >= 0;
switch (param){
case Position:
if (!src.isPositional())
return;
Vector3f pos = src.getWorldTranslation();
break;
case Velocity:
if (!src.isPositional())
return;
Vector3f vel = src.getVelocity();
break;
case MaxDistance:
if (!src.isPositional())
return;
break;
case RefDistance:
if (!src.isPositional())
return;
break;
case ReverbFilter:
if (!src.isPositional() || !src.isReverbEnabled())
return;
break;
case ReverbEnabled:
if (!src.isPositional())
return;
if (src.isReverbEnabled()){
updateSourceParam(src, AudioParam.ReverbFilter);
}
break;
case IsPositional:
break;
case Direction:
if (!src.isDirectional())
return;
Vector3f dir = src.getDirection();
break;
case InnerAngle:
if (!src.isDirectional())
return;
break;
case OuterAngle:
if (!src.isDirectional())
return;
break;
case IsDirectional:
if (src.isDirectional()){
updateSourceParam(src, AudioParam.Direction);
updateSourceParam(src, AudioParam.InnerAngle);
updateSourceParam(src, AudioParam.OuterAngle);
}else{
}
break;
case DryFilter:
if (src.getDryFilter() != null){
Filter f = src.getDryFilter();
if (f.isUpdateNeeded()){
updateFilter(f);
}
}
break;
case Looping:
if (src.isLooping()){
}
break;
case Volume:
soundPool.setVolume(src.getChannel(), src.getVolume(), src.getVolume());
break;
case Pitch:
break;
}
}
@Override
public void updateListenerParam(Listener listener, ListenerParam param)
{
if (audioDisabled)
return;
switch (param){
case Position:
Vector3f pos = listener.getLocation();
break;
case Rotation:
Vector3f dir = listener.getDirection();
Vector3f up = listener.getUp();
break;
case Velocity:
Vector3f vel = listener.getVelocity();
break;
case Volume:
//alListenerf(AL_GAIN, listener.getVolume());
break;
}
}
public void update(float tpf)
{
// does nothing
}
public void updateInThread(float tpf)
{
if (audioDisabled)
return;
if (!audioDisabled)
return;
}
public void setListener(Listener listener)
{
if (audioDisabled)
return;
if (this.listener != null){
// previous listener no longer associated with current
// renderer
this.listener.setRenderer(null);
}
this.listener = listener;
this.listener.setRenderer(this);
}
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status)
{
//lastLoadCompleted.set(true);
if (status == 0)
{
AudioNode src = mapLoadingAudioNodes.get(sampleId);
if (src.getAudioData() instanceof AndroidAudioData)
{
AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
int channelIndex;
channelIndex = soundPool.play(audioData.getSoundId(), 1f, 1f, 1, -1, 1f);
src.setChannel(channelIndex);
// Playing started ?
if (src.getChannel() > 0)
{
src.setStatus(Status.Playing);
}
}
else
{
throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
}
}
}
@Override
public void cleanup()
{
if (soundPool != null)
{
for (AudioNode src: mapLoadingAudioNodes.values())
{
if ((src.getStatus() == Status.Playing) && (src.getChannel() > 0))
{
soundPool.stop(src.getChannel());
}
if (src.getAudioData() instanceof AndroidAudioData)
{
AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
if (audioData.getSoundId() > 0)
{
soundPool.unload(audioData.getSoundId());
}
}
}
soundPool.release();
soundPool = null;
}
}
public void playSourceInstance(AudioNode src)
{
if (audioDisabled)
return;
AndroidAudioData audioData;
int soundId = 0;
if (src.getAudioData() instanceof AndroidAudioData)
{
audioData = (AndroidAudioData)src.getAudioData();
if (audioData.isUpdateNeeded() || (audioData.getSoundId() == 0))
{
if (audioData.getSoundId() > 0)
{
if (src.getChannel() > 0)
{
soundPool.stop(src.getChannel());
src.setChannel(-1);
}
soundPool.unload(audioData.getSoundId());
}
try
{
soundId = soundPool.load(am.openFd(audioData.getAssetKey().getName()), 1);
}
catch (IOException e)
{
logger.log(Level.SEVERE, "Failed to load sound " + audioData.getAssetKey().getName(), e);
soundId = -1;
}
audioData.setSoundId(soundId);
}
}
else
{
throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
}
// Sound failed to load ?
if (audioData.getSoundId() <= 0)
{
throw new IllegalArgumentException("Failed to load: " + audioData.getAssetKey().getName());
}
else
{
int channelIndex;
channelIndex = soundPool.play(audioData.getSoundId(), 1f, 1f, 1, -1, 1f);
if (channelIndex == 0)
{
// Loading is not finished
// Store the soundId and the AudioNode for async loading and later play start
mapLoadingAudioNodes.put(audioData.getSoundId(), src);
}
src.setChannel(channelIndex);
}
// Playing started ?
if (src.getChannel() > 0)
{
src.setStatus(Status.Playing);
}
}
public void playSource(AudioNode src)
{
if (audioDisabled)
return;
//assert src.getStatus() == Status.Stopped || src.getChannel() == -1;
if (src.getStatus() == Status.Playing)
{
return;
}
else if (src.getStatus() == Status.Stopped)
{
playSourceInstance(src);
}
}
public void pauseSource(AudioNode src)
{
if (audioDisabled)
return;
if (src.getStatus() == Status.Playing)
{
assert src.getChannel() != -1;
if (src.getChannel() > 0)
{
soundPool.pause(src.getChannel());
}
src.setStatus(Status.Paused);
}
}
public void stopSource(AudioNode src)
{
if (audioDisabled)
return;
if (src.getStatus() != Status.Stopped){
int chan = src.getChannel();
assert chan != -1; // if it's not stopped, must have id
if (src.getChannel() > 0)
{
soundPool.stop(src.getChannel());
src.setChannel(-1);
}
src.setStatus(Status.Stopped);
}
AndroidAudioData audioData;
if (src.getAudioData() instanceof AndroidAudioData)
{
audioData = (AndroidAudioData)src.getAudioData();
if (audioData.getSoundId() > 0)
{
soundPool.unload(audioData.getSoundId());
}
audioData.setSoundId(0);
}
else
{
throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
}
}
private int convertFormat(AudioData ad)
{
/*
switch (ad.getBitsPerSample()){
case 8:
if (ad.getChannels() == 1)
return AL_FORMAT_MONO8;
else if (ad.getChannels() == 2)
return AL_FORMAT_STEREO8;
break;
case 16:
if (ad.getChannels() == 1)
return AL_FORMAT_MONO16;
else
return AL_FORMAT_STEREO16;
}
*/
throw new UnsupportedOperationException("Unsupported channels/bits combination: "+
"bits="+ad.getBitsPerSample()+", channels="+ad.getChannels());
}
public void updateAudioData(AndroidAudioData data)
{
throw new UnsupportedOperationException("updateAudioData");
}
@Override
public void deleteAudioData(AudioData ad)
{
if (ad instanceof AndroidAudioData)
{
if (((AndroidAudioData)ad).getSoundId() > 0)
{
soundPool.unload(((AndroidAudioData)ad).getSoundId());
}
((AndroidAudioData)ad).setSoundId(0);
}
else
{
throw new IllegalArgumentException("AudioData is not of type AndroidAudioData in deleteAudioData");
}
}
@Override
public void setEnvironment(Environment env) {
// TODO Auto-generated method stub
}
}

@ -0,0 +1,27 @@
package com.jme3.audio.plugins;
import java.io.IOException;
import java.io.InputStream;
import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetLoader;
import com.jme3.audio.android.AndroidAudioData;
public class AndroidAudioLoader implements AssetLoader
{
@Override
public Object load(AssetInfo assetInfo) throws IOException
{
InputStream in = assetInfo.openStream();
if (in != null)
{
in.close();
}
AndroidAudioData result = new AndroidAudioData();
result.setAssetKey( assetInfo.getKey() );
return result;
}
}

@ -1,6 +1,7 @@
package com.jme3.system;
import android.app.Activity;
import android.content.res.Resources;
import com.jme3.util.AndroidLogHandler;
import com.jme3.asset.AndroidAssetManager;
@ -12,6 +13,7 @@ import com.jme3.audio.AudioRenderer;
import com.jme3.audio.Environment;
import com.jme3.audio.Listener;
import com.jme3.audio.ListenerParam;
import com.jme3.audio.android.AndroidAudioRenderer;
//import com.jme3.audio.DummyAudioRenderer;
import com.jme3.system.JmeContext.Type;
import com.jme3.system.android.OGLESContext;
@ -93,9 +95,11 @@ public class JmeSystem
private static boolean initialized = false;
private static boolean lowPermissions = false;
private static Resources res;
private static Activity activity;
public static void initialize(AppSettings settings)
{
if (initialized)
return;
@ -116,7 +120,7 @@ public class JmeSystem
public static String getFullName()
{
return "jMonkey Engine 3 ALPHA 0.6 Android";
return "jMonkey Engine 3 ALPHA 0.7 Android";
}
public static void setLowPermissions(boolean lowPerm)
@ -137,28 +141,7 @@ public class JmeSystem
public static AudioRenderer newAudioRenderer(AppSettings settings)
{
return new AudioRenderer()
{
public void setListener(Listener listener) {}
public void setEnvironment(Environment env) {}
public void playSourceInstance(AudioNode src) {}
public void playSource(AudioNode src) {}
public void pauseSource(AudioNode src) {}
public void stopSource(AudioNode src) {}
public void deleteAudioData(AudioData ad) {}
public void initialize() {}
public void update(float tpf) {}
public void cleanup() {}
public void updateListenerParam(Listener listener,
ListenerParam param) {
// TODO Auto-generated method stub
}
public void updateSourceParam(AudioNode src, AudioParam param) {
// TODO Auto-generated method stub
}
};
return new AndroidAudioRenderer(activity);
}
public static void setResources(Resources res)
@ -171,6 +154,17 @@ public class JmeSystem
return res;
}
public static void setActivity(Activity activity)
{
JmeSystem.activity = activity;
}
public static Activity getActivity()
{
return activity;
}
public static AssetManager newAssetManager()
{
logger.info("newAssetManager()");

@ -25,6 +25,8 @@ public class AndroidConfigChooser implements EGLConfigChooser
protected ConfigType type;
protected int pixelFormat;
protected boolean verbose = false;
private final static int EGL_OPENGL_ES2_BIT = 4;
public enum ConfigType
@ -39,9 +41,10 @@ public class AndroidConfigChooser implements EGLConfigChooser
BEST
}
public AndroidConfigChooser(ConfigType type)
public AndroidConfigChooser(ConfigType type, boolean verbose)
{
this.type = type;
this.verbose = verbose;
}
/**
@ -69,10 +72,15 @@ public class AndroidConfigChooser implements EGLConfigChooser
//Querying actual configurations
EGLConfig[] conf = new EGLConfig[configurations];
egl.eglGetConfigs(display, conf, configurations, num_conf);
int[] value = new int[1];
if (configurations <= 0)
{
logger.severe("###ERROR### ZERO EGL Configurations found, This Is a Problem");
}
// Loop over all configs to get the best
for(int i = 0; i < configurations; i++)
{
@ -94,27 +102,57 @@ public class AndroidConfigChooser implements EGLConfigChooser
bestConfig = better(bestConfig, conf[i], egl, display);
fastestConfig = faster(fastestConfig, conf[i], egl, display);
logger.info("Supported EGL Configuration #" + i );
logEGLConfig(conf[i], display, egl);
if (verbose)
{
logger.info("** Supported EGL Configuration #" + i );
logEGLConfig(conf[i], display, egl);
}
}
else
{
if (verbose)
{
logger.info("NOT Supported EGL Configuration #" + i + " EGL_OPENGL_ES2_BIT not set");
logEGLConfig(conf[i], display, egl);
}
}
}
else
{
if (verbose)
{
logger.info("NOT Supported EGL Configuration #" + i + " EGL_DEPTH_SIZE != 16");
logEGLConfig(conf[i], display, egl);
}
}
}
else
{
if (verbose)
{
logger.info("NOT Supported EGL Configuration #" + i + " EGL_WINDOW_BIT not set");
logEGLConfig(conf[i], display, egl);
}
}
}
else
{
break;
logger.severe("###ERROR### EGL Configuration #" + i + " is NULL");
}
}
if ((type == ConfigType.BEST) && (bestConfig != null))
{
logger.info("### JME3 ### using best EGL configuration available here: ");
logger.info("JME3 using best EGL configuration available here: ");
choosenConfig = bestConfig;
}
else
{
logger.info("### JME3 ### using fastest EGL configuration available here: ");
if (fastestConfig != null)
{
logger.info("JME3 using fastest EGL configuration available here: ");
}
choosenConfig = fastestConfig;
}
@ -127,7 +165,7 @@ public class AndroidConfigChooser implements EGLConfigChooser
}
else
{
logger.severe("Unable to get a valid OpenGL ES 2.0 config");
logger.severe("###ERROR### Unable to get a valid OpenGL ES 2.0 config, nether Fastest nor Best found! Bug. Please report this.");
clientOpenGLESVersion = 1;
pixelFormat = PixelFormat.UNKNOWN;
return false;

@ -75,7 +75,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
protected final AtomicBoolean created = new AtomicBoolean(false);
protected final AtomicBoolean renderable = new AtomicBoolean(false);
protected final AtomicBoolean needClose = new AtomicBoolean(false);
protected final Object createdLock = new Object();
protected final AppSettings settings = new AppSettings(true);
/* >= OpenGL ES 2.0 (Android 2.2+) */
@ -127,7 +127,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
*/
public GLSurfaceView createView(AndroidInput view)
{
return createView(view, ConfigType.FASTEST);
return createView(view, ConfigType.FASTEST, false);
}
/**
@ -136,7 +136,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
* @param debugflags 0, GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS
* @return GLSurfaceView The newly created view
*/
public GLSurfaceView createView(AndroidInput view, ConfigType configType)
public GLSurfaceView createView(AndroidInput view, ConfigType configType, boolean eglConfigVerboseLogging)
{
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
@ -151,7 +151,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
this.view = view;
// Create a config chooser
AndroidConfigChooser configChooser = new AndroidConfigChooser(configType);
AndroidConfigChooser configChooser = new AndroidConfigChooser(configType, eglConfigVerboseLogging);
// Init chooser
if (!configChooser.findConfig(egl, display))
{
@ -239,18 +239,24 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
* De-initialize in the OpenGL thread.
*/
protected void deinitInThread()
{
if (renderer != null)
renderer.cleanup();
listener.destroy();
// do android specific cleaning here
logger.info("Display destroyed.");
renderable.set(false);
created.set(false);
renderer = null;
timer = null;
{
if (renderable.get())
{
renderable.set(false);
if (renderer != null)
renderer.cleanup();
listener.destroy();
listener = null;
renderer = null;
timer = null;
// do android specific cleaning here
logger.info("Display destroyed.");
created.set(false);
}
}
protected void applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings)
@ -441,12 +447,10 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
protected void waitFor(boolean createdVal)
{
synchronized (createdLock){
while (created.get() != createdVal){
try {
createdLock.wait();
} catch (InterruptedException ex) {
}
while (created.get() != createdVal){
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
}
}
}

Loading…
Cancel
Save