1 package org.ppsspp.ppsspp; 2 3 import android.opengl.GLSurfaceView.EGLConfigChooser; 4 import android.util.Log; 5 import javax.microedition.khronos.egl.EGL10; 6 import javax.microedition.khronos.egl.EGLConfig; 7 import javax.microedition.khronos.egl.EGLDisplay; 8 9 public class NativeEGLConfigChooser implements EGLConfigChooser { 10 private static final String TAG = "NativeEGLConfigChooser"; 11 12 private static final int EGL_OPENGL_ES2_BIT = 4; 13 14 NativeEGLConfigChooser() { init(String model, int deviceType, String languageRegion, String apkPath, String dataDir, String externalStorageDir, String extFilesDir, String additionalStorageDirs, String libraryDir, String cacheDir, String shortcutParam, int androidVersion, String board)15 } 16 17 private class ConfigAttribs { 18 EGLConfig config; 19 public int red; 20 public int green; 21 public int blue; 22 public int alpha; 23 public int stencil; 24 public int depth; 25 public int samples; 26 27 public void Log() { 28 Log.i(TAG, "EGLConfig: red=" + red + " green=" + green + " blue=" + blue + " alpha=" + alpha + " depth=" + depth + " stencil=" + stencil + " samples=" + samples); 29 } 30 } isLandscape()31 32 int getEglConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attr) { 33 int[] value = new int[1]; 34 try { 35 if (egl.eglGetConfigAttrib(display, config, attr, value)) 36 return value[0]; 37 else 38 return -1; 39 } catch (IllegalArgumentException e) { 40 if (config == null) { 41 Log.e(TAG, "Called getEglConfigAttrib with null config. Bad developer."); 42 } else { 43 Log.e(TAG, "Illegal argument to getEglConfigAttrib: attr=" + attr); 44 } 45 return -1; 46 } 47 } 48 49 ConfigAttribs[] getConfigAttribs(EGL10 egl, EGLDisplay display, EGLConfig[] configs) { touch(float x, float y, int data, int pointerId)50 ConfigAttribs[] attr = new ConfigAttribs[configs.length]; 51 for (int i = 0; i < configs.length; i++) { accelerometer(float x, float y, float z)52 ConfigAttribs cfg = new ConfigAttribs(); 53 cfg.config = configs[i]; sendMessage(String msg, String arg)54 cfg.red = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE); sendInputBox(String seqID, boolean result, String value)55 cfg.green = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_GREEN_SIZE); 56 cfg.blue = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_BLUE_SIZE); queryConfig(String queryName)57 cfg.alpha = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_ALPHA_SIZE); 58 cfg.depth = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_DEPTH_SIZE); getSelectedCamera()59 cfg.stencil = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_STENCIL_SIZE); setGpsDataAndroid(long time, float hdop, float latitude, float longitude, float altitude, float speed, float bearing)60 cfg.samples = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_SAMPLES); setSatInfoAndroid(short index, short id, short elevation, short azimuth, short snr, short good)61 attr[i] = cfg; pushCameraImageAndroid(byte[] image)62 } 63 return attr; 64 } 65 66 @Override 67 public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 68 // The absolute minimum. We will do our best to choose a better config though. 69 int[] configSpec = { 70 EGL10.EGL_RED_SIZE, 5, 71 EGL10.EGL_GREEN_SIZE, 6, 72 EGL10.EGL_BLUE_SIZE, 5, 73 EGL10.EGL_DEPTH_SIZE, 16, 74 EGL10.EGL_STENCIL_SIZE, 0, 75 EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, 76 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 77 // EGL10.EGL_TRANSPARENT_TYPE, EGL10.EGL_NONE 78 EGL10.EGL_NONE 79 }; 80 81 int[] num_config = new int[1]; 82 if (!egl.eglChooseConfig(display, configSpec, null, 0, num_config)) { 83 throw new IllegalArgumentException("eglChooseConfig failed when counting"); 84 } 85 86 int numConfigs = num_config[0]; 87 Log.i(TAG, "There are " + numConfigs + " egl configs"); 88 if (numConfigs <= 0) { 89 throw new IllegalArgumentException("No configs match configSpec"); 90 } 91 92 EGLConfig[] eglConfigs = new EGLConfig[numConfigs]; 93 if (!egl.eglChooseConfig(display, configSpec, eglConfigs, numConfigs, num_config)) { 94 throw new IllegalArgumentException("eglChooseConfig failed when retrieving"); 95 } 96 97 ConfigAttribs[] configs = getConfigAttribs(egl, display, eglConfigs); 98 99 ConfigAttribs chosen = null; 100 101 // Log them all. 102 for (int i = 0; i < configs.length; i++) { 103 configs[i].Log(); 104 } 105 106 // We now ignore destination alpha as a workaround for the Mali issue 107 // where we get badly composited if we use it. 108 // Though, that may be possible to fix by using EGL10.EGL_TRANSPARENT_TYPE, EGL10.EGL_NONE. 109 110 // First, find our ideal configuration. Prefer depth. 111 for (int i = 0; i < configs.length; i++) { 112 ConfigAttribs c = configs[i]; 113 if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 24) { 114 chosen = c; 115 break; 116 } 117 } 118 119 if (chosen == null) { 120 // Then, prefer one with 20-bit depth (Tegra 3) 121 for (int i = 0; i < configs.length; i++) { 122 ConfigAttribs c = configs[i]; 123 if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 20) { 124 chosen = c; 125 break; 126 } 127 } 128 } 129 130 if (chosen == null) { 131 // Second, accept one with 16-bit depth. 132 for (int i = 0; i < configs.length; i++) { 133 ConfigAttribs c = configs[i]; 134 if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 16) { 135 chosen = c; 136 break; 137 } 138 } 139 } 140 141 if (chosen == null) { 142 // Third, accept one with no stencil. 143 for (int i = 0; i < configs.length; i++) { 144 ConfigAttribs c = configs[i]; 145 if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.depth >= 16) { 146 chosen = c; 147 break; 148 } 149 } 150 } 151 152 if (chosen == null) { 153 // Third, accept one with alpha but with stencil, 24-bit depth. 154 for (int i = 0; i < configs.length; i++) { 155 ConfigAttribs c = configs[i]; 156 if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth >= 24) { 157 chosen = c; 158 break; 159 } 160 } 161 } 162 163 if (chosen == null) { 164 // Third, accept one with alpha but with stencil, 16-bit depth. 165 for (int i = 0; i < configs.length; i++) { 166 ConfigAttribs c = configs[i]; 167 if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth >= 16) { 168 chosen = c; 169 break; 170 } 171 } 172 } 173 174 if (chosen == null) { 175 // Fourth, accept one with 16-bit color but depth and stencil required. 176 for (int i = 0; i < configs.length; i++) { 177 ConfigAttribs c = configs[i]; 178 if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16 && c.stencil >= 8) { 179 chosen = c; 180 break; 181 } 182 } 183 } 184 185 if (chosen == null) { 186 // Fifth, accept one with 16-bit color but depth required. 187 for (int i = 0; i < configs.length; i++) { 188 ConfigAttribs c = configs[i]; 189 if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16) { 190 chosen = c; 191 break; 192 } 193 } 194 } 195 196 if (chosen == null) { 197 // Final, accept the first one in the list. 198 if (configs.length > 0) 199 chosen = configs[0]; 200 } 201 202 if (chosen == null) { 203 throw new IllegalArgumentException("Failed to find a valid EGL config"); 204 } 205 206 Log.i(TAG, "Final chosen config: "); 207 chosen.Log(); 208 return chosen.config; 209 } 210 } 211