[Scummvm-cvs-logs] SF.net SVN: scummvm:[53808] scummvm/trunk/backends/platform/android/org/ inodes/gus/scummvm/ScummVM.java

anguslees at users.sourceforge.net anguslees at users.sourceforge.net
Mon Oct 25 10:50:17 CEST 2010


Revision: 53808
          http://scummvm.svn.sourceforge.net/scummvm/?rev=53808&view=rev
Author:   anguslees
Date:     2010-10-25 08:50:16 +0000 (Mon, 25 Oct 2010)

Log Message:
-----------
ANDROID: Don't trust eglChooseConfig and refilter/sort results manually

It seems some Android versions and devices (eg Droid) don't implement
eglChooseConfig according to spec and the first result isn't the best
choice.  Implement our own filtering / scoring to workaround this.

Modified Paths:
--------------
    scummvm/trunk/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java

Modified: scummvm/trunk/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
===================================================================
--- scummvm/trunk/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java	2010-10-25 08:26:21 UTC (rev 53807)
+++ scummvm/trunk/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java	2010-10-25 08:50:16 UTC (rev 53808)
@@ -23,6 +23,8 @@
 
 import java.io.File;
 import java.util.concurrent.Semaphore;
+import java.util.Map;
+import java.util.LinkedHashMap;
 
 
 // At least in Android 2.1, eglCreateWindowSurface() requires an
@@ -109,6 +111,51 @@
 		}
 	}
 
+	// For debugging
+	private static final Map<String, Integer> attribs;
+	static {
+		attribs = new LinkedHashMap<String, Integer>();
+		attribs.put("CONFIG_ID", EGL10.EGL_CONFIG_ID);
+		attribs.put("BUFFER_SIZE", EGL10.EGL_BUFFER_SIZE);
+		attribs.put("RED_SIZE", EGL10.EGL_RED_SIZE);
+		attribs.put("GREEN_SIZE", EGL10.EGL_GREEN_SIZE);
+		attribs.put("BLUE_SIZE", EGL10.EGL_BLUE_SIZE);
+		attribs.put("ALPHA_SIZE", EGL10.EGL_ALPHA_SIZE);
+		//attribs.put("BIND_TO_RGB", EGL10.EGL_BIND_TO_TEXTURE_RGB);
+		//attribs.put("BIND_TO_RGBA", EGL10.EGL_BIND_TO_TEXTURE_RGBA);
+		attribs.put("CONFIG_CAVEAT", EGL10.EGL_CONFIG_CAVEAT);
+		attribs.put("DEPTH_SIZE", EGL10.EGL_DEPTH_SIZE);
+		attribs.put("LEVEL", EGL10.EGL_LEVEL);
+		attribs.put("MAX_PBUFFER_WIDTH", EGL10.EGL_MAX_PBUFFER_WIDTH);
+		attribs.put("MAX_PBUFFER_HEIGHT", EGL10.EGL_MAX_PBUFFER_HEIGHT);
+		attribs.put("MAX_PBUFFER_PIXELS", EGL10.EGL_MAX_PBUFFER_PIXELS);
+		//attribs.put("MAX_SWAP_INTERVAL", EGL10.EGL_MAX_SWAP_INTERVAL);
+		//attribs.put("MIN_SWAP_INTERVAL", EGL10.EGL_MIN_SWAP_INTERVAL);
+		attribs.put("NATIVE_RENDERABLE", EGL10.EGL_NATIVE_RENDERABLE);
+		attribs.put("NATIVE_VISUAL_ID", EGL10.EGL_NATIVE_VISUAL_ID);
+		attribs.put("NATIVE_VISUAL_TYPE", EGL10.EGL_NATIVE_VISUAL_TYPE);
+		attribs.put("SAMPLE_BUFFERS", EGL10.EGL_SAMPLE_BUFFERS);
+		attribs.put("SAMPLES", EGL10.EGL_SAMPLES);
+		attribs.put("STENCIL_SIZE", EGL10.EGL_STENCIL_SIZE);
+		attribs.put("SURFACE_TYPE", EGL10.EGL_SURFACE_TYPE);
+		attribs.put("TRANSPARENT_TYPE", EGL10.EGL_TRANSPARENT_TYPE);
+		attribs.put("TRANSPARENT_RED_VALUE", EGL10.EGL_TRANSPARENT_RED_VALUE);
+		attribs.put("TRANSPARENT_GREEN_VALUE", EGL10.EGL_TRANSPARENT_GREEN_VALUE);
+		attribs.put("TRANSPARENT_BLUE_VALUE", EGL10.EGL_TRANSPARENT_BLUE_VALUE);
+	}
+	private void dumpEglConfig(EGLConfig config) {
+		int[] value = new int[1];
+		for (Map.Entry<String, Integer> entry : attribs.entrySet()) {
+			egl.eglGetConfigAttrib(eglDisplay, config,
+								   entry.getValue(), value);
+			if (value[0] == EGL10.EGL_NONE)
+				Log.d(LOG_TAG, entry.getKey() + ": NONE");
+			else
+				Log.d(LOG_TAG, String.format("%s: %d",
+											 entry.getKey(), value[0]));
+		}
+	}
+
 	// Called by ScummVM thread (from initBackend)
 	private void createScummVMGLContext() {
 		egl = (EGL10)EGLContext.getEGL();
@@ -125,24 +172,90 @@
 		EGLConfig[] configs = new EGLConfig[numConfigs];
 		egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs,
 							num_config);
-		eglConfig = configs[0];
 
+		if (false) {
+			Log.d(LOG_TAG,
+				  String.format("Found %d EGL configurations.", numConfigs));
+			for (EGLConfig config : configs)
+				dumpEglConfig(config);
+		}
+
+		// Android's eglChooseConfig is busted in several versions and
+		// devices so we have to filter/rank the configs again ourselves.
+		eglConfig = chooseEglConfig(configs);
+		if (false) {
+			Log.d(LOG_TAG,
+				  String.format("Chose EGL config from %d possibilities.", numConfigs));
+			dumpEglConfig(eglConfig);
+		}
+
 		eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
 										  EGL10.EGL_NO_CONTEXT, null);
+		if (eglContext == EGL10.EGL_NO_CONTEXT)
+			throw new RuntimeException("Failed to create context");
 	}
 
+	private EGLConfig chooseEglConfig(EGLConfig[] configs) {
+		int best = 0;
+		int bestScore = -1;
+		int[] value = new int[1];
+		for (int i = 0; i < configs.length; i++) {
+			EGLConfig config = configs[i];
+			int score = 10000;
+			egl.eglGetConfigAttrib(eglDisplay, config,
+								   EGL10.EGL_SURFACE_TYPE, value);
+			if ((value[0] & EGL10.EGL_WINDOW_BIT) == 0)
+				continue;  // must have
+
+			egl.eglGetConfigAttrib(eglDisplay, config,
+								   EGL10.EGL_CONFIG_CAVEAT, value);
+			if (value[0] != EGL10.EGL_NONE)
+				score -= 1000;
+
+			// Must be at least 555, but then smaller is better
+			final int[] colorBits = {EGL10.EGL_RED_SIZE,
+									 EGL10.EGL_GREEN_SIZE,
+									 EGL10.EGL_BLUE_SIZE,
+									 EGL10.EGL_ALPHA_SIZE};
+			for (int component : colorBits) {
+				egl.eglGetConfigAttrib(eglDisplay, config,
+									   component, value);
+				if (value[0] >= 5)
+					score += 10;   // boost if >5 bits accuracy
+				score -= value[0]; // penalize for wasted bits
+			}
+
+			egl.eglGetConfigAttrib(eglDisplay, config,
+								   EGL10.EGL_DEPTH_SIZE, value);
+			score -= value[0];  // penalize for wasted bits
+
+			if (score > bestScore) {
+				best = i;
+				bestScore = score;
+			}
+		}
+
+		if (bestScore < 0) {
+			Log.e(LOG_TAG, "Unable to find an acceptable EGL config, expect badness.");
+			return configs[0];
+		}
+
+		return configs[best];
+	}
+
 	// Called by ScummVM thread
 	static private boolean _log_version = true;
 	protected void setupScummVMSurface() {
 		try {
 			surfaceLock.acquire();
 		} catch (InterruptedException e) {
-			Log.e(this.toString(),
-				  "Interrupted while waiting for surface lock", e);
+			Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e);
 			return;
 		}
 		eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
 												nativeSurface, null);
+		if (eglSurface == EGL10.EGL_NO_SURFACE)
+			Log.e(LOG_TAG,  "CreateWindowSurface failed!");
 		egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
 
 		GL10 gl = (GL10)eglContext.getGL();
@@ -302,8 +415,8 @@
 		if (buf_size < 0) {
 			int guess = AUDIO_FRAME_SIZE * sample_rate / 100;  // 10ms of audio
 			Log.w(LOG_TAG, String.format(
-										 "Unable to get min audio buffer size (error %d). Guessing %dB.",
-										 buf_size, guess));
+				"Unable to get min audio buffer size (error %d). Guessing %dB.",
+				buf_size, guess));
 			buf_size = guess;
 		}
 		Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio",


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list