diff --git a/engine/src/android/com/jme3/app/AndroidHarness.java b/engine/src/android/com/jme3/app/AndroidHarness.java
index 36397338b..d292daf17 100644
--- a/engine/src/android/com/jme3/app/AndroidHarness.java
+++ b/engine/src/android/com/jme3/app/AndroidHarness.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();
}
}
diff --git a/engine/src/android/com/jme3/asset/AndroidAssetManager.java b/engine/src/android/com/jme3/asset/AndroidAssetManager.java
index d9e87203b..88f24ff4f 100644
--- a/engine/src/android/com/jme3/asset/AndroidAssetManager.java
+++ b/engine/src/android/com/jme3/asset/AndroidAssetManager.java
@@ -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;
/**
* AndroidAssetManager
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");
diff --git a/engine/src/android/com/jme3/audio/android/AndroidAudioData.java b/engine/src/android/com/jme3/audio/android/AndroidAudioData.java
new file mode 100644
index 000000000..39f729154
--- /dev/null
+++ b/engine/src/android/com/jme3/audio/android/AndroidAudioData.java
@@ -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
+
+ }
+
+
+
+}
diff --git a/engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java b/engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java
new file mode 100644
index 000000000..b9afae089
--- /dev/null
+++ b/engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java
@@ -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 mapLoadingAudioNodes = new HashMap();
+
+ 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
+
+ }
+
+
+
+
+}
diff --git a/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java b/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java
new file mode 100644
index 000000000..4c20619c7
--- /dev/null
+++ b/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java
@@ -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;
+ }
+
+}
diff --git a/engine/src/android/com/jme3/system/JmeSystem.java b/engine/src/android/com/jme3/system/JmeSystem.java
index 2628b31fb..a7481e975 100644
--- a/engine/src/android/com/jme3/system/JmeSystem.java
+++ b/engine/src/android/com/jme3/system/JmeSystem.java
@@ -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()");
diff --git a/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java b/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
index 12d8f593f..f082b5f79 100644
--- a/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
+++ b/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
@@ -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;
diff --git a/engine/src/android/com/jme3/system/android/OGLESContext.java b/engine/src/android/com/jme3/system/android/OGLESContext.java
index a75dd8096..bedc9e634 100644
--- a/engine/src/android/com/jme3/system/android/OGLESContext.java
+++ b/engine/src/android/com/jme3/system/android/OGLESContext.java
@@ -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) {
}
}
}