mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-06 11:06:18 +02:00
207 lines
6.2 KiB
Java
207 lines
6.2 KiB
Java
package com.henrikrydgard.libnative;
|
|
|
|
import javax.microedition.khronos.egl.EGL10;
|
|
import javax.microedition.khronos.egl.EGLConfig;
|
|
import javax.microedition.khronos.egl.EGLDisplay;
|
|
|
|
import android.opengl.GLSurfaceView.EGLConfigChooser;
|
|
import android.util.Log;
|
|
|
|
public class NativeEGLConfigChooser implements EGLConfigChooser {
|
|
private static final String TAG = "NativeEGLConfigChooser";
|
|
|
|
private static final int EGL_OPENGL_ES2_BIT = 4;
|
|
|
|
private class ConfigAttribs {
|
|
EGLConfig config;
|
|
public int red;
|
|
public int green;
|
|
public int blue;
|
|
public int alpha;
|
|
public int stencil;
|
|
public int depth;
|
|
public int samples;
|
|
public void Log() {
|
|
Log.i(TAG, "EGLConfig: red=" + red + " green=" + green + " blue=" + blue + " alpha=" + alpha + " depth=" + depth + " stencil=" + stencil + " samples=" + samples);
|
|
}
|
|
}
|
|
|
|
int getEglConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attr) {
|
|
int[] value = new int[1];
|
|
try {
|
|
if (egl.eglGetConfigAttrib(display, config, attr, value))
|
|
return value[0];
|
|
else
|
|
return -1;
|
|
} catch (IllegalArgumentException e) {
|
|
if (config == null) {
|
|
Log.e(TAG, "Called getEglConfigAttrib with null config. Bad developer.");
|
|
} else {
|
|
Log.e(TAG, "Illegal argument to getEglConfigAttrib: attr=" + attr);
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ConfigAttribs[] getConfigAttribs(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
|
|
ConfigAttribs[] attr = new ConfigAttribs[configs.length];
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs cfg = new ConfigAttribs();
|
|
cfg.config = configs[i];
|
|
cfg.red = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE);
|
|
cfg.green = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_GREEN_SIZE);
|
|
cfg.blue = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_BLUE_SIZE);
|
|
cfg.alpha = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_ALPHA_SIZE);
|
|
cfg.depth = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_DEPTH_SIZE);
|
|
cfg.stencil = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_STENCIL_SIZE);
|
|
cfg.samples = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_SAMPLES);
|
|
attr[i] = cfg;
|
|
}
|
|
return attr;
|
|
}
|
|
|
|
@Override
|
|
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
|
// The absolute minimum. We will do our best to choose a better config though.
|
|
int[] configSpec = {
|
|
EGL10.EGL_RED_SIZE, 5,
|
|
EGL10.EGL_GREEN_SIZE, 6,
|
|
EGL10.EGL_BLUE_SIZE, 5,
|
|
EGL10.EGL_DEPTH_SIZE, 16,
|
|
EGL10.EGL_STENCIL_SIZE, 0,
|
|
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
|
|
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
EGL10.EGL_NONE
|
|
};
|
|
|
|
int[] num_config = new int[1];
|
|
if (!egl.eglChooseConfig(display, configSpec, null, 0, num_config)) {
|
|
throw new IllegalArgumentException("eglChooseConfig failed when counting");
|
|
}
|
|
|
|
int numConfigs = num_config[0];
|
|
Log.i(TAG, "There are " + numConfigs + " egl configs");
|
|
if (numConfigs <= 0) {
|
|
throw new IllegalArgumentException("No configs match configSpec");
|
|
}
|
|
|
|
EGLConfig[] eglConfigs = new EGLConfig[numConfigs];
|
|
if (!egl.eglChooseConfig(display, configSpec, eglConfigs, numConfigs, num_config)) {
|
|
throw new IllegalArgumentException("eglChooseConfig failed when retrieving");
|
|
}
|
|
|
|
ConfigAttribs [] configs = getConfigAttribs(egl, display, eglConfigs);
|
|
|
|
ConfigAttribs chosen = null;
|
|
|
|
// Log them all.
|
|
for (int i = 0; i < configs.length; i++) {
|
|
configs[i].Log();
|
|
}
|
|
|
|
// We now ignore destination alpha as a workaround for the Mali issue
|
|
// where we get badly composited if we use it.
|
|
|
|
// First, find our ideal configuration. Prefer depth.
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs c = configs[i];
|
|
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 24) {
|
|
chosen = c;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (chosen == null) {
|
|
// Then, prefer one with 20-bit depth (Tegra 3)
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs c = configs[i];
|
|
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 20) {
|
|
chosen = c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chosen == null) {
|
|
// Second, accept one with 16-bit depth.
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs c = configs[i];
|
|
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 16) {
|
|
chosen = c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chosen == null) {
|
|
// Third, accept one with no stencil.
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs c = configs[i];
|
|
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.depth >= 16) {
|
|
chosen = c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chosen == null) {
|
|
// Third, accept one with alpha but with stencil.
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs c = configs[i];
|
|
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth >= 24) {
|
|
chosen = c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chosen == null) {
|
|
// Third, accept one with alpha but with stencil.
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs c = configs[i];
|
|
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth >= 16) {
|
|
chosen = c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chosen == null) {
|
|
// Fourth, accept one with 16-bit color but depth and stencil required.
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs c = configs[i];
|
|
if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16 && c.stencil >= 8) {
|
|
chosen = c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chosen == null) {
|
|
// Fifth, accept one with 16-bit color but depth required.
|
|
for (int i = 0; i < configs.length; i++) {
|
|
ConfigAttribs c = configs[i];
|
|
if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16) {
|
|
chosen = c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chosen == null) {
|
|
// Final, accept the first one in the list.
|
|
if (configs.length > 0)
|
|
chosen = configs[0];
|
|
}
|
|
|
|
if (chosen == null) {
|
|
throw new IllegalArgumentException("Failed to find a valid EGL config");
|
|
}
|
|
|
|
Log.i(TAG, "Final chosen config: ");
|
|
chosen.Log();
|
|
return chosen.config;
|
|
}
|
|
|
|
}
|