diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/ScreenConfigChooser.java b/SPD-classes/src/main/java/com/watabou/glwrap/ScreenConfigChooser.java new file mode 100644 index 000000000..0382a77ae --- /dev/null +++ b/SPD-classes/src/main/java/com/watabou/glwrap/ScreenConfigChooser.java @@ -0,0 +1,172 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.watabou.glwrap; + +import android.opengl.EGL14; +import android.opengl.GLSurfaceView; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLDisplay; + +public class ScreenConfigChooser implements GLSurfaceView.EGLConfigChooser { + + private int[] attribVals = new int[6]; //array for storing attribute values + private int[] attribPrefs = new int[6]; //array for storing attribute preferences + + //array of corresponding EGL attributes for each array index + private int[] attribEGLconsts = new int[]{ + EGL10.EGL_RED_SIZE, + EGL10.EGL_GREEN_SIZE, + EGL10.EGL_BLUE_SIZE, + EGL10.EGL_ALPHA_SIZE, + EGL10.EGL_DEPTH_SIZE, + EGL10.EGL_STENCIL_SIZE + }; + + //attributes with this preference are ignored + public static final int DONT_CARE = 0; + + //attributes with this preference must be present in the config at exactly the given value + public static final int EXACTLY = 1; + + //attributes with this preference must be present in the config with at least the given value + // In the case of multiple valid configs, chooser will prefer higher values for these attributes + public static final int AT_LEAST = 2; + + //attributes with this preference must be present in the config with at most the given value + // In the case of multiple valid configs, chooser will prefer higher values for these attributes + public static final int AT_MOST = 3; + + + private EGL10 egl; + private EGLDisplay display; + + public ScreenConfigChooser(){ + this( false ); + } + + public ScreenConfigChooser( boolean depth ){ + this( false, depth ); + } + + //helper constructor for a basic config with or without depth + //and whether or not to force RGB565 for performance reasons + //On many devices RGB565 gives slightly better performance for a minimal quality tradeoff. + public ScreenConfigChooser( boolean forceRGB565, boolean depth ){ + this( + new int[]{ 5, 6, 5, 0, depth ? 16 : 0, 0 } , + forceRGB565 ? + new int[]{ EXACTLY, EXACTLY, EXACTLY, EXACTLY, EXACTLY, EXACTLY } : + new int[]{ AT_LEAST, AT_LEAST, AT_LEAST, EXACTLY, EXACTLY, EXACTLY } + ); + } + + public ScreenConfigChooser( int[] vals, int[] prefs){ + if (vals.length != 6 || prefs.length != 6) + throw new IllegalArgumentException("6 values must be entered!"); + + attribVals = vals; + attribPrefs = prefs; + } + + int[] eglPrefs = new int[]{ + EGL10.EGL_RENDERABLE_TYPE, 4, //same as EGL_OPENGL_ES2_BIT. config must support GLES 2.0 + EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, + EGL10.EGL_NONE + }; + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + + this.egl = egl; + this.display = display; + + int[] num = new int[1]; + if (!egl.eglChooseConfig(display, eglPrefs, null, 0, num)) { + throw new IllegalArgumentException("eglChooseConfig failed"); + } + + EGLConfig[] configs = new EGLConfig[num[0]]; + if (!egl.eglChooseConfig(display, eglPrefs, configs, num[0], num)) { + throw new IllegalArgumentException("eglChooseConfig failed"); + } + + EGLConfig config = chooseConfig(configs); + if (config == null) { + throw new IllegalArgumentException("No config chosen"); + } + return config; + + } + + private EGLConfig chooseConfig( EGLConfig[] configs ){ + EGLConfig bestConfig = null; + int bestConfigValue = -1; + for (EGLConfig config : configs){ + + int configVal = 0; + + for (int i = 0; i < attribEGLconsts.length; i++){ + int val = findConfigAttrib(config, attribEGLconsts[i]); + + if (attribPrefs[i] == EXACTLY && attribVals[i] != val) { + configVal = -1; + break; + } else if (attribPrefs[i] == AT_LEAST) { + if (attribVals[i] > val) { + configVal = -1; + break; + } else { + configVal += val; + } + break; + } else if (attribPrefs[i] == AT_MOST) { + if (attribVals[i] < val) { + configVal = -1; + break; + } else { + configVal += val; + } + } + } + + if (configVal > bestConfigValue){ + bestConfigValue = configVal; + bestConfig = config; + } + + } + return bestConfig; + } + + int[] value = new int[1]; + + private int findConfigAttrib(EGLConfig config, int attribute) { + + if (egl.eglGetConfigAttrib(display, config, attribute, value)) { + return value[0]; + } else { + throw new IllegalArgumentException("eglGetConfigAttrib failed"); + } + } +} diff --git a/SPD-classes/src/main/java/com/watabou/noosa/Game.java b/SPD-classes/src/main/java/com/watabou/noosa/Game.java index 9ffd27131..776db5f29 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/Game.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/Game.java @@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10; import com.watabou.glscripts.Script; import com.watabou.gltextures.TextureCache; +import com.watabou.glwrap.ScreenConfigChooser; import com.watabou.glwrap.Vertexbuffer; import com.watabou.input.Keys; import com.watabou.input.Touchscreen; @@ -42,6 +43,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.media.AudioManager; import android.opengl.GLES20; import android.opengl.GLSurfaceView; +import android.os.Build; import android.os.Bundle; import android.os.Vibrator; import android.util.DisplayMetrics; @@ -129,7 +131,13 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou view = new GLSurfaceView( this ); view.setEGLContextClientVersion( 2 ); - view.setEGLConfigChooser( 5, 6, 5, 0, 0, 0 ); + + //Versions of android below 4.0.0 are forced to RGB 565 for performance reasons. + //Otherwise try to use RGB888 for best quality, but use RGB565 if it is what's available. + view.setEGLConfigChooser( new ScreenConfigChooser( + Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN, + false )); + view.setRenderer( this ); view.setOnTouchListener( this ); setContentView( view ); @@ -320,11 +328,11 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou Game.timeScale = 1f; Game.timeTotal = 0f; } - + protected void update() { Game.elapsed = Game.timeScale * step * 0.001f; Game.timeTotal += Game.elapsed; - + synchronized (motionEvents) { Touchscreen.processTouchEvents( motionEvents ); motionEvents.clear();