import android.os.Debug;\r
import android.os.Handler;\r
import android.util.Log;\r
+import android.view.Gravity;\r
import android.view.View;\r
import android.view.Window;\r
import android.view.WindowManager;\r
\r
+import android.widget.FrameLayout;\r
import com.badlogic.gdx.Application;\r
import com.badlogic.gdx.ApplicationListener;\r
import com.badlogic.gdx.Audio;\r
import com.badlogic.gdx.Graphics;\r
import com.badlogic.gdx.Input;\r
import com.badlogic.gdx.Version;\r
+import com.badlogic.gdx.backends.android.surfaceview.FillResolutionStrategy;\r
import com.badlogic.gdx.backends.android.surfaceview.GLSurfaceViewCupcake;\r
+import com.badlogic.gdx.backends.android.surfaceview.ResolutionStrategy;\r
import com.badlogic.gdx.graphics.GL10;\r
import com.badlogic.gdx.graphics.GL11;\r
\r
/**\r
* An implementation of the {@link Application} interface for Android. Create an {@link Activity} that derives from this class. In\r
- * the {@link Activity#onCreate(Bundle)} method call the {@link #initialize(ApplicationListener,boolean)} method specifying the\r
+ * the {@link Activity#onCreate(Bundle)} method call the {@link #initialize(ApplicationListener, boolean)} method specifying the\r
* configuration for the GLSurfaceView.\r
- * \r
+ *\r
* @author mzechner\r
*/\r
public class AndroidApplication extends Activity implements Application {\r
\r
- static {\r
- Version.loadLibrary();\r
- }\r
-\r
- protected AndroidGraphics graphics;\r
- protected AndroidInput input;\r
- protected AndroidAudio audio;\r
- protected AndroidFiles files;\r
- protected ApplicationListener listener;\r
- protected Handler handler;\r
- protected boolean firstResume = true;\r
-\r
- /**\r
- * This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get\r
- * input, render via OpenGL and so on. If useGL20IfAvailable is set the AndroidApplication will try to create an OpenGL ES 2.0\r
- * context which can then be used via {@link Graphics#getGL20()}. The {@link GL10} and {@link GL11} interfaces should not be\r
- * used when OpenGL ES 2.0 is enabled. To query whether enabling OpenGL ES 2.0 was successful use the\r
- * {@link Graphics#isGL20Available()} method. Sleep time in touch event handler is 0, so no sleeping is performed.\r
- * \r
- * @param listener the {@link ApplicationListener} implementing the program logic\r
- * @param useGL2IfAvailable whether to use OpenGL ES 2.0 if its available.\r
- */\r
- public void initialize (ApplicationListener listener, boolean useGL2IfAvailable) {\r
- initialize(listener, useGL2IfAvailable, 0);\r
- }\r
-\r
- /**\r
- * This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get\r
- * input, render via OpenGL and so on. If useGL20IfAvailable is set the AndroidApplication will try to create an OpenGL ES 2.0\r
- * context which can then be used via {@link Graphics#getGL20()}. The {@link GL10} and {@link GL11} interfaces should not be\r
- * used when OpenGL ES 2.0 is enabled. To query whether enabling OpenGL ES 2.0 was successful use the\r
- * {@link Graphics#isGL20Available()} method. sleepTime specifies the number of milliseconds to sleep in the touch event\r
- * handler. This may be used on <= 1.6 Android devices. Note that it will not solve the CPU usage problem of the event handler\r
- * of the Android system. Things will still slow down.\r
- * \r
- * @param listener the {@link ApplicationListener} implementing the program logic\r
- * @param useGL2IfAvailable whether to use OpenGL ES 2.0 if its available.\r
- * @param sleepTime specifies the number of milliseconds to sleep in the touch event handler\r
- */\r
- public void initialize (ApplicationListener listener, boolean useGL2IfAvailable, int sleepTime) {\r
- graphics = new AndroidGraphics(this, useGL2IfAvailable);\r
- input = new AndroidInput(this, graphics.view, sleepTime);\r
- audio = new AndroidAudio(this);\r
- files = new AndroidFiles(this.getAssets());\r
- this.listener = listener;\r
- this.handler = new Handler();\r
-\r
- Gdx.app = this;\r
- Gdx.input = this.getInput();\r
- Gdx.audio = this.getAudio();\r
- Gdx.files = this.getFiles();\r
- Gdx.graphics = this.getGraphics();\r
-\r
- requestWindowFeature(Window.FEATURE_NO_TITLE);\r
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);\r
- setContentView(graphics.getView());\r
- }\r
-\r
- /**\r
- * This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get\r
- * input, render via OpenGL and so on. If useGL20IfAvailable is set the AndroidApplication will try to create an OpenGL ES 2.0\r
- * context which can then be used via {@link Graphics#getGL20()}. The {@link GL10} and {@link GL11} interfaces should not be\r
- * used when OpenGL ES 2.0 is enabled. To query whether enabling OpenGL ES 2.0 was successful use the\r
- * {@link Graphics#isGL20Available()} method. sleepTime specifies the number of milliseconds to sleep in the touch event\r
- * handler. This may be used on <= 1.6 Android devices. Note that it will not solve the CPU usage problem of the event handler\r
- * of the Android system. Things will still slow down.\r
- * \r
- * Note: you have to add the returned view to your layout!\r
- * \r
- * @param listener the {@link ApplicationListener} implementing the program logic\r
- * @param useGL2IfAvailable whether to use OpenGL ES 2.0 if its available.\r
- * @param sleepTime specifies the number of milliseconds to sleep in the touch event handler\r
- * @return the GLSurfaceView of the application\r
- */\r
- public View initializeForView (ApplicationListener listener, boolean useGL2IfAvailable, int sleepTime) {\r
- graphics = new AndroidGraphics(this, useGL2IfAvailable);\r
- input = new AndroidInput(this, graphics.view, sleepTime);\r
- audio = new AndroidAudio(this);\r
- files = new AndroidFiles(this.getAssets());\r
- this.listener = listener;\r
- this.handler = new Handler();\r
-\r
- Gdx.app = this;\r
- Gdx.input = this.getInput();\r
- Gdx.audio = this.getAudio();\r
- Gdx.files = this.getFiles();\r
- Gdx.graphics = this.getGraphics();\r
-\r
- return graphics.getView();\r
- }\r
-\r
- @Override protected void onPause () {\r
- graphics.pause();\r
-\r
- if (isFinishing()) {\r
- graphics.clearManagedCaches();\r
- graphics.destroy();\r
- }\r
-\r
- if (graphics != null && graphics.view != null) {\r
- if (graphics.view instanceof GLSurfaceViewCupcake) ((GLSurfaceViewCupcake)graphics.view).onPause();\r
- if (graphics.view instanceof android.opengl.GLSurfaceView) ((android.opengl.GLSurfaceView)graphics.view).onPause();\r
- }\r
-\r
- if (audio != null) audio.pause();\r
- super.onPause();\r
- }\r
-\r
- @Override protected void onResume () {\r
- Gdx.app = this;\r
- Gdx.input = this.getInput();\r
- Gdx.audio = this.getAudio();\r
- Gdx.files = this.getFiles();\r
- Gdx.graphics = this.getGraphics();\r
-\r
- if (graphics != null && graphics.view != null) {\r
- if (graphics.view instanceof GLSurfaceViewCupcake) ((GLSurfaceViewCupcake)graphics.view).onResume();\r
- if (graphics.view instanceof android.opengl.GLSurfaceView) ((android.opengl.GLSurfaceView)graphics.view).onResume();\r
- }\r
-\r
- if (audio != null) audio.resume();\r
- if (!firstResume)\r
- graphics.resume();\r
- else\r
- firstResume = false;\r
- super.onResume();\r
- }\r
-\r
- @Override protected void onDestroy () {\r
- audio.dispose();\r
- super.onDestroy();\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public Audio getAudio () {\r
- return audio;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public Files getFiles () {\r
- return files;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public Graphics getGraphics () {\r
- return graphics;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public Input getInput () {\r
- return input;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public void log (String tag, String message) {\r
- Log.d(tag, message);\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public ApplicationType getType () {\r
- return ApplicationType.Android;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public int getVersion () {\r
- return Build.VERSION.SDK.charAt(0) - '0';\r
- }\r
-\r
- @Override public long getJavaHeap () {\r
- return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();\r
- }\r
-\r
- @Override public long getNativeHeap () {\r
- return Debug.getNativeHeapAllocatedSize();\r
- }\r
+ static {\r
+ Version.loadLibrary();\r
+ }\r
+\r
+ protected AndroidGraphics graphics;\r
+ protected AndroidInput input;\r
+ protected AndroidAudio audio;\r
+ protected AndroidFiles files;\r
+ protected ApplicationListener listener;\r
+ protected Handler handler;\r
+ protected boolean firstResume = true;\r
+\r
+ /**\r
+ * This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get\r
+ * input, render via OpenGL and so on. If useGL20IfAvailable is set the AndroidApplication will try to create an OpenGL ES 2.0\r
+ * context which can then be used via {@link Graphics#getGL20()}. The {@link GL10} and {@link GL11} interfaces should not be\r
+ * used when OpenGL ES 2.0 is enabled. To query whether enabling OpenGL ES 2.0 was successful use the\r
+ * {@link Graphics#isGL20Available()} method. Sleep time in touch event handler is 0, so no sleeping is performed.\r
+ *\r
+ * @param listener the {@link ApplicationListener} implementing the program logic\r
+ * @param useGL2IfAvailable whether to use OpenGL ES 2.0 if its available.\r
+ */\r
+ public void initialize(ApplicationListener listener, boolean useGL2IfAvailable) {\r
+ initialize(listener, useGL2IfAvailable, new FillResolutionStrategy(), 0);\r
+ }\r
+\r
+ /**\r
+ * This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get\r
+ * input, render via OpenGL and so on. If useGL20IfAvailable is set the AndroidApplication will try to create an OpenGL ES 2.0\r
+ * context which can then be used via {@link Graphics#getGL20()}. The {@link GL10} and {@link GL11} interfaces should not be\r
+ * used when OpenGL ES 2.0 is enabled. To query whether enabling OpenGL ES 2.0 was successful use the\r
+ * {@link Graphics#isGL20Available()} method. sleepTime specifies the number of milliseconds to sleep in the touch event\r
+ * handler. This may be used on <= 1.6 Android devices. Note that it will not solve the CPU usage problem of the event handler\r
+ * of the Android system. Things will still slow down.\r
+ *\r
+ * @param listener the {@link ApplicationListener} implementing the program logic\r
+ * @param useGL2IfAvailable whether to use OpenGL ES 2.0 if its available.\r
+ * @param sleepTime specifies the number of milliseconds to sleep in the touch event handler\r
+ */\r
+ public void initialize(ApplicationListener listener, boolean useGL2IfAvailable, ResolutionStrategy resolutionStrategy, int sleepTime) {\r
+ graphics = new AndroidGraphics(this, useGL2IfAvailable, resolutionStrategy);\r
+ input = new AndroidInput(this, graphics.view, sleepTime);\r
+ audio = new AndroidAudio(this);\r
+ files = new AndroidFiles(this.getAssets());\r
+ this.listener = listener;\r
+ this.handler = new Handler();\r
+\r
+ Gdx.app = this;\r
+ Gdx.input = this.getInput();\r
+ Gdx.audio = this.getAudio();\r
+ Gdx.files = this.getFiles();\r
+ Gdx.graphics = this.getGraphics();\r
+\r
+ requestWindowFeature(Window.FEATURE_NO_TITLE);\r
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);\r
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);\r
+ setContentView(graphics.getView(), createLayoutParams());\r
+ }\r
+\r
+ protected FrameLayout.LayoutParams createLayoutParams() {\r
+ FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.FILL_PARENT);\r
+ layoutParams.gravity = Gravity.CENTER;\r
+ return layoutParams;\r
+ }\r
+\r
+ /**\r
+ * This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get\r
+ * input, render via OpenGL and so on. If useGL20IfAvailable is set the AndroidApplication will try to create an OpenGL ES 2.0\r
+ * context which can then be used via {@link Graphics#getGL20()}. The {@link GL10} and {@link GL11} interfaces should not be\r
+ * used when OpenGL ES 2.0 is enabled. To query whether enabling OpenGL ES 2.0 was successful use the\r
+ * {@link Graphics#isGL20Available()} method. sleepTime specifies the number of milliseconds to sleep in the touch event\r
+ * handler. This may be used on <= 1.6 Android devices. Note that it will not solve the CPU usage problem of the event handler\r
+ * of the Android system. Things will still slow down.\r
+ * <p/>\r
+ * Note: you have to add the returned view to your layout!\r
+ *\r
+ * @param listener the {@link ApplicationListener} implementing the program logic\r
+ * @param useGL2IfAvailable whether to use OpenGL ES 2.0 if its available.\r
+ * @param sleepTime specifies the number of milliseconds to sleep in the touch event handler\r
+ * @return the GLSurfaceView of the application\r
+ */\r
+ public View initializeForView(ApplicationListener listener, boolean useGL2IfAvailable, ResolutionStrategy resolutionStrategy, int sleepTime) {\r
+ graphics = new AndroidGraphics(this, useGL2IfAvailable, resolutionStrategy);\r
+ input = new AndroidInput(this, graphics.view, sleepTime);\r
+ audio = new AndroidAudio(this);\r
+ files = new AndroidFiles(this.getAssets());\r
+ this.listener = listener;\r
+ this.handler = new Handler();\r
+\r
+ Gdx.app = this;\r
+ Gdx.input = this.getInput();\r
+ Gdx.audio = this.getAudio();\r
+ Gdx.files = this.getFiles();\r
+ Gdx.graphics = this.getGraphics();\r
+\r
+ return graphics.getView();\r
+ }\r
+\r
+ @Override\r
+ protected void onPause() {\r
+ graphics.pause();\r
+\r
+ if (isFinishing()) {\r
+ graphics.clearManagedCaches();\r
+ graphics.destroy();\r
+ }\r
+\r
+ if (graphics != null && graphics.view != null) {\r
+ if (graphics.view instanceof GLSurfaceViewCupcake) ((GLSurfaceViewCupcake) graphics.view).onPause();\r
+ if (graphics.view instanceof android.opengl.GLSurfaceView)\r
+ ((android.opengl.GLSurfaceView) graphics.view).onPause();\r
+ }\r
+\r
+ if (audio != null) audio.pause();\r
+ super.onPause();\r
+ }\r
+\r
+ @Override\r
+ protected void onResume() {\r
+ Gdx.app = this;\r
+ Gdx.input = this.getInput();\r
+ Gdx.audio = this.getAudio();\r
+ Gdx.files = this.getFiles();\r
+ Gdx.graphics = this.getGraphics();\r
+\r
+ if (graphics != null && graphics.view != null) {\r
+ if (graphics.view instanceof GLSurfaceViewCupcake) ((GLSurfaceViewCupcake) graphics.view).onResume();\r
+ if (graphics.view instanceof android.opengl.GLSurfaceView)\r
+ ((android.opengl.GLSurfaceView) graphics.view).onResume();\r
+ }\r
+\r
+ if (audio != null) audio.resume();\r
+ if (!firstResume)\r
+ graphics.resume();\r
+ else\r
+ firstResume = false;\r
+ super.onResume();\r
+ }\r
+\r
+ @Override\r
+ protected void onDestroy() {\r
+ audio.dispose();\r
+ super.onDestroy();\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Audio getAudio() {\r
+ return audio;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Files getFiles() {\r
+ return files;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Graphics getGraphics() {\r
+ return graphics;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Input getInput() {\r
+ return input;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public void log(String tag, String message) {\r
+ Log.d(tag, message);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public ApplicationType getType() {\r
+ return ApplicationType.Android;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public int getVersion() {\r
+ return Build.VERSION.SDK.charAt(0) - '0';\r
+ }\r
+\r
+ @Override\r
+ public long getJavaHeap() {\r
+ return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();\r
+ }\r
+\r
+ @Override\r
+ public long getNativeHeap() {\r
+ return Debug.getNativeHeapAllocatedSize();\r
+ }\r
}\r
\r
package com.badlogic.gdx.backends.android;\r
\r
-import java.io.InputStream;\r
-\r
-import javax.microedition.khronos.egl.EGL10;\r
-import javax.microedition.khronos.egl.EGLConfig;\r
-import javax.microedition.khronos.egl.EGLContext;\r
-import javax.microedition.khronos.egl.EGLDisplay;\r
-\r
import android.app.Activity;\r
import android.graphics.Bitmap;\r
import android.graphics.BitmapFactory;\r
import android.util.DisplayMetrics;\r
import android.view.Display;\r
import android.view.View;\r
-\r
import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.Graphics;\r
-import com.badlogic.gdx.backends.android.surfaceview.GLSurfaceView20;\r
-import com.badlogic.gdx.backends.android.surfaceview.GLSurfaceViewCupcake;\r
+import com.badlogic.gdx.backends.android.surfaceview.*;\r
import com.badlogic.gdx.files.FileHandle;\r
-import com.badlogic.gdx.graphics.GL10;\r
-import com.badlogic.gdx.graphics.GL11;\r
-import com.badlogic.gdx.graphics.GL20;\r
-import com.badlogic.gdx.graphics.GLCommon;\r
-import com.badlogic.gdx.graphics.Mesh;\r
-import com.badlogic.gdx.graphics.Pixmap;\r
+import com.badlogic.gdx.graphics.*;\r
import com.badlogic.gdx.graphics.Pixmap.Format;\r
-import com.badlogic.gdx.graphics.Texture;\r
import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
-import com.badlogic.gdx.graphics.TextureData;\r
import com.badlogic.gdx.graphics.glutils.FrameBuffer;\r
import com.badlogic.gdx.graphics.glutils.ShaderProgram;\r
import com.badlogic.gdx.math.WindowedMean;\r
import com.badlogic.gdx.utils.GdxRuntimeException;\r
import com.badlogic.gdx.utils.MathUtils;\r
\r
+import javax.microedition.khronos.egl.EGL10;\r
+import javax.microedition.khronos.egl.EGLConfig;\r
+import javax.microedition.khronos.egl.EGLContext;\r
+import javax.microedition.khronos.egl.EGLDisplay;\r
+import java.io.InputStream;\r
+\r
/**\r
* An implementation of {@link Graphics} for Android.\r
- * \r
+ *\r
* @author mzechner\r
*/\r
public final class AndroidGraphics implements Graphics, Renderer {\r
- final View view;\r
- int width;\r
- int height;\r
- AndroidApplication app;\r
- GLCommon gl;\r
- GL10 gl10;\r
- GL11 gl11;\r
- GL20 gl20;\r
-\r
- private long lastFrameTime = System.nanoTime();\r
- private float deltaTime = 0;\r
- private long frameStart = System.nanoTime();\r
- private int frames = 0;\r
- private int fps;\r
- private WindowedMean mean = new WindowedMean(5);\r
-\r
- volatile boolean created = false;\r
- volatile boolean running = false;\r
- volatile boolean pause = false;\r
- volatile boolean resume = false;\r
- volatile boolean destroy = false;\r
-\r
- private float ppiX = 0;\r
- private float ppiY = 0;\r
- private float ppcX = 0;\r
- private float ppcY = 0;\r
-\r
- public AndroidGraphics (AndroidApplication activity, boolean useGL2IfAvailable) {\r
- view = createGLSurfaceView(activity, useGL2IfAvailable);\r
- this.app = activity;\r
- }\r
-\r
- private View createGLSurfaceView (Activity activity, boolean useGL2) {\r
- EGLConfigChooser configChooser = getEglConfigChooser();\r
-\r
- if (useGL2 && checkGL20()) {\r
- GLSurfaceView20 view = new GLSurfaceView20(activity);\r
- if (configChooser != null) view.setEGLConfigChooser(configChooser);\r
- view.setRenderer(this); \r
- return view;\r
- } else {\r
- if (Integer.parseInt(android.os.Build.VERSION.SDK) <= 4) {\r
- GLSurfaceViewCupcake view = new GLSurfaceViewCupcake(activity);\r
- if (configChooser != null) view.setEGLConfigChooser(configChooser);\r
- view.setRenderer(this);\r
- return view;\r
- } else {\r
- android.opengl.GLSurfaceView view = new android.opengl.GLSurfaceView(activity);\r
- if (configChooser != null) view.setEGLConfigChooser(configChooser);\r
- view.setRenderer(this); \r
- return view;\r
- }\r
- }\r
- }\r
-\r
- private EGLConfigChooser getEglConfigChooser () {\r
- if (!Build.DEVICE.equalsIgnoreCase("GT-I7500"))\r
- return null;\r
- else\r
- return new android.opengl.GLSurfaceView.EGLConfigChooser() {\r
-\r
- public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display) {\r
-\r
- // Ensure that we get a 16bit depth-buffer. Otherwise, we'll fall\r
- // back to Pixelflinger on some device (read: Samsung I7500)\r
- int[] attributes = new int[] {EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE};\r
- EGLConfig[] configs = new EGLConfig[1];\r
- int[] result = new int[1];\r
- egl.eglChooseConfig(display, attributes, configs, 1, result);\r
- return configs[0];\r
- }\r
- };\r
- }\r
-\r
- private void updatePpi () {\r
- DisplayMetrics metrics = new DisplayMetrics();\r
- app.getWindowManager().getDefaultDisplay().getMetrics(metrics);\r
-\r
- ppiX = metrics.xdpi;\r
- ppiY = metrics.ydpi;\r
- ppcX = metrics.xdpi / 2.54f;\r
- ppcY = metrics.ydpi / 2.54f;\r
- }\r
-\r
- private boolean checkGL20 () {\r
- EGL10 egl = (EGL10)EGLContext.getEGL();\r
- EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);\r
-\r
- int[] version = new int[2];\r
- egl.eglInitialize(display, version);\r
-\r
- int EGL_OPENGL_ES2_BIT = 4;\r
- int[] configAttribs = {EGL10.EGL_RED_SIZE, 4, EGL10.EGL_GREEN_SIZE, 4, EGL10.EGL_BLUE_SIZE, 4, EGL10.EGL_RENDERABLE_TYPE,\r
- EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE};\r
-\r
- EGLConfig[] configs = new EGLConfig[10];\r
- int[] num_config = new int[1];\r
- egl.eglChooseConfig(display, configAttribs, configs, 10, num_config);\r
- egl.eglTerminate(display);\r
- return num_config[0] > 0;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public GL10 getGL10 () {\r
- return gl10;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public GL11 getGL11 () {\r
- return gl11;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public GL20 getGL20 () {\r
- return gl20;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public int getHeight () {\r
- return height;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public int getWidth () {\r
- return width;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public boolean isGL11Available () {\r
- return gl11 != null;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public boolean isGL20Available () {\r
- return gl20 != null;\r
- }\r
-\r
- private static boolean isPowerOfTwo (int value) {\r
- return ((value != 0) && (value & (value - 1)) == 0);\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public Pixmap newPixmap (int width, int height, Format format) {\r
- return new AndroidPixmap(width, height, format);\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public Pixmap newPixmap (InputStream in) {\r
- Bitmap bitmap = BitmapFactory.decodeStream(in);\r
- if (bitmap == null) throw new GdxRuntimeException("Couldn't load Pixmap from InputStream");\r
- return new AndroidPixmap(bitmap);\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public Pixmap newPixmap (FileHandle file) {\r
- return newPixmap(file.read());\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public Pixmap newPixmap (Object nativePixmap) {\r
- return new AndroidPixmap((Bitmap)nativePixmap);\r
- }\r
-\r
- /**\r
- * This instantiates the GL10, GL11 and GL20 instances. Includes the check for certain devices that pretend to support GL11 but\r
- * fuck up vertex buffer objects. This includes the pixelflinger which segfaults when buffers are deleted as well as the\r
- * Motorola CLIQ and the Samsung Behold II.\r
- * \r
- * @param gl\r
- */\r
- private void setupGL (javax.microedition.khronos.opengles.GL10 gl) {\r
- if (gl10 != null || gl20 != null) return;\r
-\r
- if (view instanceof GLSurfaceView20) {\r
- gl20 = new AndroidGL20();\r
- this.gl = gl20;\r
- } else {\r
- gl10 = new AndroidGL10(gl);\r
- this.gl = gl10;\r
- if (gl instanceof javax.microedition.khronos.opengles.GL11) {\r
- String renderer = gl.glGetString(GL10.GL_RENDERER);\r
- if (!renderer.toLowerCase().contains("pixelflinger")\r
- && !(android.os.Build.MODEL.equals("MB200") || android.os.Build.MODEL.equals("MB220") || android.os.Build.MODEL\r
- .contains("Behold"))) {\r
- gl11 = new AndroidGL11((javax.microedition.khronos.opengles.GL11)gl);\r
- gl10 = gl11;\r
- }\r
- }\r
- }\r
-\r
- Gdx.gl = this.gl;\r
- Gdx.gl10 = gl10;\r
- Gdx.gl11 = gl11;\r
- Gdx.gl20 = gl20;\r
-\r
- Gdx.app.log("AndroidGraphics", "OGL renderer: " + gl.glGetString(GL10.GL_RENDERER));\r
- Gdx.app.log("AndroidGraphics", "OGL vendor: " + gl.glGetString(GL10.GL_VENDOR));\r
- Gdx.app.log("AndroidGraphics", "OGL version: " + gl.glGetString(GL10.GL_VERSION));\r
- Gdx.app.log("AndroidGraphics", "OGL extensions: " + gl.glGetString(GL10.GL_EXTENSIONS));\r
- }\r
-\r
- @Override public void onSurfaceChanged (javax.microedition.khronos.opengles.GL10 gl, int width, int height) {\r
- this.width = width;\r
- this.height = height;\r
- updatePpi();\r
- app.listener.resize(width, height);\r
- }\r
-\r
- @Override public void onSurfaceCreated (javax.microedition.khronos.opengles.GL10 gl, EGLConfig config) {\r
- setupGL(gl);\r
- logConfig(config);\r
- updatePpi();\r
-\r
- Mesh.invalidateAllMeshes();\r
- AndroidTexture.invalidateAllTextures();\r
- ShaderProgram.invalidateAllShaderPrograms();\r
- FrameBuffer.invalidateAllFrameBuffers();\r
-\r
- Display display = app.getWindowManager().getDefaultDisplay();\r
- this.width = display.getWidth();\r
- this.height = display.getHeight();\r
- mean = new WindowedMean(5);\r
- this.lastFrameTime = System.nanoTime();\r
-\r
- gl.glViewport(0, 0, this.width, this.height);\r
-\r
- if (created == false) {\r
- app.listener.create();\r
- created = true;\r
- synchronized (this) {\r
- running = true;\r
- }\r
- }\r
- }\r
-\r
- private void logConfig (EGLConfig config) {\r
- EGL10 egl = (EGL10)EGLContext.getEGL();\r
- EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);\r
- int r = getAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);\r
- int g = getAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);\r
- int b = getAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);\r
- int a = getAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);\r
- int d = getAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);\r
- int s = getAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);\r
-\r
- Gdx.app.log("AndroidGraphics", "framebuffer: (" + r + ", " + g + ", " + b + ", " + a + ")");\r
- Gdx.app.log("AndroidGraphics", "depthbuffer: (" + d + ")");\r
- Gdx.app.log("AndroidGraphics", "stencilbuffer: (" + s + ")");\r
- }\r
-\r
- int[] value = new int[1];\r
-\r
- private int getAttrib (EGL10 egl, EGLDisplay display, EGLConfig config, int attrib, int defValue) {\r
- if (egl.eglGetConfigAttrib(display, config, attrib, value)) {\r
- return value[0];\r
- }\r
- return defValue;\r
- }\r
-\r
- Object synch = new Object();\r
-\r
- void resume () {\r
- synchronized (synch) {\r
- running = true;\r
- resume = true;\r
- }\r
- }\r
-\r
- void pause () {\r
- synchronized (synch) {\r
- running = false;\r
- pause = true;\r
- while (pause) {\r
- try {\r
- synch.wait();\r
- } catch (InterruptedException ignored) {\r
- }\r
- }\r
- }\r
- }\r
-\r
- void destroy () {\r
- synchronized (synch) {\r
- running = false;\r
- destroy = true;\r
-\r
- while (destroy) {\r
- try {\r
- synch.wait();\r
- } catch (InterruptedException ex) {\r
- }\r
- }\r
- }\r
- }\r
-\r
- @Override public void onDrawFrame (javax.microedition.khronos.opengles.GL10 gl) {\r
- long time = System.nanoTime();\r
- deltaTime = (time - lastFrameTime) / 1000000000.0f;\r
- lastFrameTime = time;\r
- mean.addValue(deltaTime);\r
-\r
- boolean lrunning = false;\r
- boolean lpause = false;\r
- boolean ldestroy = false;\r
- boolean lresume = false;\r
-\r
- synchronized (synch) {\r
- lrunning = running;\r
- lpause = pause;\r
- ldestroy = destroy;\r
- lresume = resume;\r
-\r
- if (resume) {\r
- resume = false;\r
- }\r
-\r
- if (pause) {\r
- pause = false;\r
- synch.notifyAll();\r
- }\r
-\r
- if (destroy) {\r
- destroy = false;\r
- synch.notifyAll();\r
- }\r
- }\r
-\r
- if (lresume) {\r
- app.listener.resume();\r
- Gdx.app.log("AndroidGraphics", "resumed");\r
- }\r
-\r
- if (lrunning) {\r
- app.input.processEvents();\r
- app.listener.render();\r
- }\r
-\r
- if (lpause) {\r
- app.listener.pause();\r
- Gdx.app.log("AndroidGraphics", "paused");\r
- }\r
-\r
- if (ldestroy) {\r
- app.listener.dispose();\r
- Gdx.app.log("AndroidGraphics", "destroyed");\r
- }\r
-\r
- if (time - frameStart > 1000000000) {\r
- fps = frames;\r
- frames = 0;\r
- frameStart = time;\r
- }\r
- frames++;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public float getDeltaTime () {\r
- return mean.getMean() == 0 ? deltaTime : mean.getMean();\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public GraphicsType getType () {\r
- return GraphicsType.AndroidGL;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public int getFramesPerSecond () {\r
- return fps;\r
- }\r
-\r
- @Override public Texture newUnmanagedTexture (int width, int height, Format format, TextureFilter minFilter,\r
- TextureFilter magFilter, TextureWrap uWrap, TextureWrap vWrap) {\r
- if (gl != gl20 && (!MathUtils.isPowerOfTwo(width) || !MathUtils.isPowerOfTwo(height)))\r
- throw new GdxRuntimeException("Dimensions have to be a power of two");\r
-\r
- Bitmap.Config config = AndroidPixmap.getInternalFormat(format);\r
- Bitmap bitmap = Bitmap.createBitmap(width, height, config);\r
- Texture texture = null;\r
- texture = new AndroidTexture(this, bitmap, minFilter, magFilter, uWrap, vWrap, false, null);\r
- bitmap.recycle();\r
- return texture;\r
- }\r
-\r
- @Override public Texture newUnmanagedTexture (Pixmap pixmap, TextureFilter minFilter, TextureFilter magFilter,\r
- TextureWrap uWrap, TextureWrap vWrap) {\r
-\r
- if (gl != gl20 && (!MathUtils.isPowerOfTwo(pixmap.getWidth()) || !MathUtils.isPowerOfTwo(pixmap.getHeight())))\r
- throw new GdxRuntimeException("Dimensions have to be a power of two");\r
-\r
- return new AndroidTexture(this, (Bitmap)pixmap.getNativePixmap(), minFilter, magFilter, uWrap, vWrap, false, null);\r
- }\r
-\r
- @Override public Texture newTexture (FileHandle file, TextureFilter minFilter, TextureFilter magFilter, TextureWrap uWrap,\r
- TextureWrap vWrap) {\r
- return new AndroidTexture(this, (Bitmap)null, minFilter, magFilter, uWrap, vWrap, true, file);\r
- }\r
-\r
- @Override public Texture newTexture (TextureData textureData, TextureFilter minFilter, TextureFilter magFilter,\r
- TextureWrap uWrap, TextureWrap vWrap) {\r
- return new AndroidTexture(this, textureData, minFilter, magFilter, uWrap, vWrap);\r
- }\r
-\r
- public void clearManagedCaches () {\r
- Mesh.clearAllMeshes();\r
- AndroidTexture.clearAllTextures();\r
- ShaderProgram.clearAllShaderPrograms();\r
- FrameBuffer.clearAllFrameBuffers();\r
- }\r
-\r
- public View getView () {\r
- return view;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- @Override public GLCommon getGLCommon () {\r
- return gl;\r
- }\r
-\r
- @Override public float getPpiX () {\r
- return ppiX;\r
- }\r
-\r
- @Override public float getPpiY () {\r
- return ppiY;\r
- }\r
-\r
- @Override public float getPpcX () {\r
- return ppcX;\r
- }\r
-\r
- @Override public float getPpcY () {\r
- return ppcY;\r
- }\r
+ final View view;\r
+ int width;\r
+ int height;\r
+ AndroidApplication app;\r
+ GLCommon gl;\r
+ GL10 gl10;\r
+ GL11 gl11;\r
+ GL20 gl20;\r
+\r
+ private long lastFrameTime = System.nanoTime();\r
+ private float deltaTime = 0;\r
+ private long frameStart = System.nanoTime();\r
+ private int frames = 0;\r
+ private int fps;\r
+ private WindowedMean mean = new WindowedMean(5);\r
+\r
+ volatile boolean created = false;\r
+ volatile boolean running = false;\r
+ volatile boolean pause = false;\r
+ volatile boolean resume = false;\r
+ volatile boolean destroy = false;\r
+\r
+ private float ppiX = 0;\r
+ private float ppiY = 0;\r
+ private float ppcX = 0;\r
+ private float ppcY = 0;\r
+\r
+ public AndroidGraphics(AndroidApplication activity, boolean useGL2IfAvailable, ResolutionStrategy resolutionStrategy) {\r
+ view = createGLSurfaceView(activity, useGL2IfAvailable, resolutionStrategy);\r
+ this.app = activity;\r
+ }\r
+\r
+ private View createGLSurfaceView(Activity activity, boolean useGL2, ResolutionStrategy resolutionStrategy) {\r
+ EGLConfigChooser configChooser = getEglConfigChooser();\r
+\r
+ if (useGL2 && checkGL20()) {\r
+ GLSurfaceView20 view = new GLSurfaceView20(activity, resolutionStrategy);\r
+ if (configChooser != null) view.setEGLConfigChooser(configChooser);\r
+ view.setRenderer(this);\r
+ return view;\r
+ } else {\r
+ if (Integer.parseInt(android.os.Build.VERSION.SDK) <= 4) {\r
+ GLSurfaceViewCupcake view = new GLSurfaceViewCupcake(activity, resolutionStrategy);\r
+ if (configChooser != null) view.setEGLConfigChooser(configChooser);\r
+ view.setRenderer(this);\r
+ return view;\r
+ } else {\r
+ android.opengl.GLSurfaceView view = new DefaultGLSurfaceView(activity, resolutionStrategy);\r
+ if (configChooser != null) view.setEGLConfigChooser(configChooser);\r
+ view.setRenderer(this);\r
+ return view;\r
+ }\r
+ }\r
+ }\r
+\r
+ private EGLConfigChooser getEglConfigChooser() {\r
+ if (!Build.DEVICE.equalsIgnoreCase("GT-I7500"))\r
+ return null;\r
+ else\r
+ return new android.opengl.GLSurfaceView.EGLConfigChooser() {\r
+\r
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {\r
+\r
+ // Ensure that we get a 16bit depth-buffer. Otherwise, we'll fall\r
+ // back to Pixelflinger on some device (read: Samsung I7500)\r
+ int[] attributes = new int[]{EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE};\r
+ EGLConfig[] configs = new EGLConfig[1];\r
+ int[] result = new int[1];\r
+ egl.eglChooseConfig(display, attributes, configs, 1, result);\r
+ return configs[0];\r
+ }\r
+ };\r
+ }\r
+\r
+ private void updatePpi() {\r
+ DisplayMetrics metrics = new DisplayMetrics();\r
+ app.getWindowManager().getDefaultDisplay().getMetrics(metrics);\r
+\r
+ ppiX = metrics.xdpi;\r
+ ppiY = metrics.ydpi;\r
+ ppcX = metrics.xdpi / 2.54f;\r
+ ppcY = metrics.ydpi / 2.54f;\r
+ }\r
+\r
+ private boolean checkGL20() {\r
+ EGL10 egl = (EGL10) EGLContext.getEGL();\r
+ EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);\r
+\r
+ int[] version = new int[2];\r
+ egl.eglInitialize(display, version);\r
+\r
+ int EGL_OPENGL_ES2_BIT = 4;\r
+ int[] configAttribs = {EGL10.EGL_RED_SIZE, 4, EGL10.EGL_GREEN_SIZE, 4, EGL10.EGL_BLUE_SIZE, 4, EGL10.EGL_RENDERABLE_TYPE,\r
+ EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE};\r
+\r
+ EGLConfig[] configs = new EGLConfig[10];\r
+ int[] num_config = new int[1];\r
+ egl.eglChooseConfig(display, configAttribs, configs, 10, num_config);\r
+ egl.eglTerminate(display);\r
+ return num_config[0] > 0;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public GL10 getGL10() {\r
+ return gl10;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public GL11 getGL11() {\r
+ return gl11;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public GL20 getGL20() {\r
+ return gl20;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public int getHeight() {\r
+ return height;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public int getWidth() {\r
+ return width;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public boolean isGL11Available() {\r
+ return gl11 != null;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public boolean isGL20Available() {\r
+ return gl20 != null;\r
+ }\r
+\r
+ private static boolean isPowerOfTwo(int value) {\r
+ return ((value != 0) && (value & (value - 1)) == 0);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Pixmap newPixmap(int width, int height, Format format) {\r
+ return new AndroidPixmap(width, height, format);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Pixmap newPixmap(InputStream in) {\r
+ Bitmap bitmap = BitmapFactory.decodeStream(in);\r
+ if (bitmap == null) throw new GdxRuntimeException("Couldn't load Pixmap from InputStream");\r
+ return new AndroidPixmap(bitmap);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Pixmap newPixmap(FileHandle file) {\r
+ return newPixmap(file.read());\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Pixmap newPixmap(Object nativePixmap) {\r
+ return new AndroidPixmap((Bitmap) nativePixmap);\r
+ }\r
+\r
+ /**\r
+ * This instantiates the GL10, GL11 and GL20 instances. Includes the check for certain devices that pretend to support GL11 but\r
+ * fuck up vertex buffer objects. This includes the pixelflinger which segfaults when buffers are deleted as well as the\r
+ * Motorola CLIQ and the Samsung Behold II.\r
+ *\r
+ * @param gl\r
+ */\r
+ private void setupGL(javax.microedition.khronos.opengles.GL10 gl) {\r
+ if (gl10 != null || gl20 != null) return;\r
+\r
+ if (view instanceof GLSurfaceView20) {\r
+ gl20 = new AndroidGL20();\r
+ this.gl = gl20;\r
+ } else {\r
+ gl10 = new AndroidGL10(gl);\r
+ this.gl = gl10;\r
+ if (gl instanceof javax.microedition.khronos.opengles.GL11) {\r
+ String renderer = gl.glGetString(GL10.GL_RENDERER);\r
+ if (!renderer.toLowerCase().contains("pixelflinger")\r
+ && !(android.os.Build.MODEL.equals("MB200") || android.os.Build.MODEL.equals("MB220") || android.os.Build.MODEL\r
+ .contains("Behold"))) {\r
+ gl11 = new AndroidGL11((javax.microedition.khronos.opengles.GL11) gl);\r
+ gl10 = gl11;\r
+ }\r
+ }\r
+ }\r
+\r
+ Gdx.gl = this.gl;\r
+ Gdx.gl10 = gl10;\r
+ Gdx.gl11 = gl11;\r
+ Gdx.gl20 = gl20;\r
+\r
+ Gdx.app.log("AndroidGraphics", "OGL renderer: " + gl.glGetString(GL10.GL_RENDERER));\r
+ Gdx.app.log("AndroidGraphics", "OGL vendor: " + gl.glGetString(GL10.GL_VENDOR));\r
+ Gdx.app.log("AndroidGraphics", "OGL version: " + gl.glGetString(GL10.GL_VERSION));\r
+ Gdx.app.log("AndroidGraphics", "OGL extensions: " + gl.glGetString(GL10.GL_EXTENSIONS));\r
+ }\r
+\r
+ @Override\r
+ public void onSurfaceChanged(javax.microedition.khronos.opengles.GL10 gl, int width, int height) {\r
+ this.width = width;\r
+ this.height = height;\r
+ updatePpi();\r
+ app.listener.resize(width, height);\r
+ }\r
+\r
+ @Override\r
+ public void onSurfaceCreated(javax.microedition.khronos.opengles.GL10 gl, EGLConfig config) {\r
+ setupGL(gl);\r
+ logConfig(config);\r
+ updatePpi();\r
+\r
+ Mesh.invalidateAllMeshes();\r
+ AndroidTexture.invalidateAllTextures();\r
+ ShaderProgram.invalidateAllShaderPrograms();\r
+ FrameBuffer.invalidateAllFrameBuffers();\r
+\r
+ Display display = app.getWindowManager().getDefaultDisplay();\r
+ this.width = display.getWidth();\r
+ this.height = display.getHeight();\r
+ mean = new WindowedMean(5);\r
+ this.lastFrameTime = System.nanoTime();\r
+\r
+ gl.glViewport(0, 0, this.width, this.height);\r
+\r
+ if (created == false) {\r
+ app.listener.create();\r
+ created = true;\r
+ synchronized (this) {\r
+ running = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ private void logConfig(EGLConfig config) {\r
+ EGL10 egl = (EGL10) EGLContext.getEGL();\r
+ EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);\r
+ int r = getAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);\r
+ int g = getAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);\r
+ int b = getAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);\r
+ int a = getAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);\r
+ int d = getAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);\r
+ int s = getAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);\r
+\r
+ Gdx.app.log("AndroidGraphics", "framebuffer: (" + r + ", " + g + ", " + b + ", " + a + ")");\r
+ Gdx.app.log("AndroidGraphics", "depthbuffer: (" + d + ")");\r
+ Gdx.app.log("AndroidGraphics", "stencilbuffer: (" + s + ")");\r
+ }\r
+\r
+ int[] value = new int[1];\r
+\r
+ private int getAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attrib, int defValue) {\r
+ if (egl.eglGetConfigAttrib(display, config, attrib, value)) {\r
+ return value[0];\r
+ }\r
+ return defValue;\r
+ }\r
+\r
+ Object synch = new Object();\r
+\r
+ void resume() {\r
+ synchronized (synch) {\r
+ running = true;\r
+ resume = true;\r
+ }\r
+ }\r
+\r
+ void pause() {\r
+ synchronized (synch) {\r
+ running = false;\r
+ pause = true;\r
+ while (pause) {\r
+ try {\r
+ synch.wait();\r
+ } catch (InterruptedException ignored) {\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ void destroy() {\r
+ synchronized (synch) {\r
+ running = false;\r
+ destroy = true;\r
+\r
+ while (destroy) {\r
+ try {\r
+ synch.wait();\r
+ } catch (InterruptedException ex) {\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void onDrawFrame(javax.microedition.khronos.opengles.GL10 gl) {\r
+ long time = System.nanoTime();\r
+ deltaTime = (time - lastFrameTime) / 1000000000.0f;\r
+ lastFrameTime = time;\r
+ mean.addValue(deltaTime);\r
+\r
+ boolean lrunning = false;\r
+ boolean lpause = false;\r
+ boolean ldestroy = false;\r
+ boolean lresume = false;\r
+\r
+ synchronized (synch) {\r
+ lrunning = running;\r
+ lpause = pause;\r
+ ldestroy = destroy;\r
+ lresume = resume;\r
+\r
+ if (resume) {\r
+ resume = false;\r
+ }\r
+\r
+ if (pause) {\r
+ pause = false;\r
+ synch.notifyAll();\r
+ }\r
+\r
+ if (destroy) {\r
+ destroy = false;\r
+ synch.notifyAll();\r
+ }\r
+ }\r
+\r
+ if (lresume) {\r
+ app.listener.resume();\r
+ Gdx.app.log("AndroidGraphics", "resumed");\r
+ }\r
+\r
+ if (lrunning) {\r
+ app.input.processEvents();\r
+ app.listener.render();\r
+ }\r
+\r
+ if (lpause) {\r
+ app.listener.pause();\r
+ Gdx.app.log("AndroidGraphics", "paused");\r
+ }\r
+\r
+ if (ldestroy) {\r
+ app.listener.dispose();\r
+ Gdx.app.log("AndroidGraphics", "destroyed");\r
+ }\r
+\r
+ if (time - frameStart > 1000000000) {\r
+ fps = frames;\r
+ frames = 0;\r
+ frameStart = time;\r
+ }\r
+ frames++;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public float getDeltaTime() {\r
+ return mean.getMean() == 0 ? deltaTime : mean.getMean();\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public GraphicsType getType() {\r
+ return GraphicsType.AndroidGL;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public int getFramesPerSecond() {\r
+ return fps;\r
+ }\r
+\r
+ @Override\r
+ public Texture newUnmanagedTexture(int width, int height, Format format, TextureFilter minFilter,\r
+ TextureFilter magFilter, TextureWrap uWrap, TextureWrap vWrap) {\r
+ if (gl != gl20 && (!MathUtils.isPowerOfTwo(width) || !MathUtils.isPowerOfTwo(height)))\r
+ throw new GdxRuntimeException("Dimensions have to be a power of two");\r
+\r
+ Bitmap.Config config = AndroidPixmap.getInternalFormat(format);\r
+ Bitmap bitmap = Bitmap.createBitmap(width, height, config);\r
+ Texture texture = null;\r
+ texture = new AndroidTexture(this, bitmap, minFilter, magFilter, uWrap, vWrap, false, null);\r
+ bitmap.recycle();\r
+ return texture;\r
+ }\r
+\r
+ @Override\r
+ public Texture newUnmanagedTexture(Pixmap pixmap, TextureFilter minFilter, TextureFilter magFilter,\r
+ TextureWrap uWrap, TextureWrap vWrap) {\r
+\r
+ if (gl != gl20 && (!MathUtils.isPowerOfTwo(pixmap.getWidth()) || !MathUtils.isPowerOfTwo(pixmap.getHeight())))\r
+ throw new GdxRuntimeException("Dimensions have to be a power of two");\r
+\r
+ return new AndroidTexture(this, (Bitmap) pixmap.getNativePixmap(), minFilter, magFilter, uWrap, vWrap, false, null);\r
+ }\r
+\r
+ @Override\r
+ public Texture newTexture(FileHandle file, TextureFilter minFilter, TextureFilter magFilter, TextureWrap uWrap,\r
+ TextureWrap vWrap) {\r
+ return new AndroidTexture(this, (Bitmap) null, minFilter, magFilter, uWrap, vWrap, true, file);\r
+ }\r
+\r
+ @Override\r
+ public Texture newTexture(TextureData textureData, TextureFilter minFilter, TextureFilter magFilter,\r
+ TextureWrap uWrap, TextureWrap vWrap) {\r
+ return new AndroidTexture(this, textureData, minFilter, magFilter, uWrap, vWrap);\r
+ }\r
+\r
+ public void clearManagedCaches() {\r
+ Mesh.clearAllMeshes();\r
+ AndroidTexture.clearAllTextures();\r
+ ShaderProgram.clearAllShaderPrograms();\r
+ FrameBuffer.clearAllFrameBuffers();\r
+ }\r
+\r
+ public View getView() {\r
+ return view;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public GLCommon getGLCommon() {\r
+ return gl;\r
+ }\r
+\r
+ @Override\r
+ public float getPpiX() {\r
+ return ppiX;\r
+ }\r
+\r
+ @Override\r
+ public float getPpiY() {\r
+ return ppiY;\r
+ }\r
+\r
+ @Override\r
+ public float getPpcX() {\r
+ return ppcX;\r
+ }\r
+\r
+ @Override\r
+ public float getPpcY() {\r
+ return ppcY;\r
+ }\r
}\r
--- /dev/null
+package com.badlogic.gdx.backends.android.surfaceview;\r
+\r
+import android.content.Context;\r
+import android.opengl.GLSurfaceView;\r
+import android.util.AttributeSet;\r
+\r
+public class DefaultGLSurfaceView extends GLSurfaceView {\r
+\r
+\r
+ final ResolutionStrategy resolutionStrategy;\r
+\r
+ public DefaultGLSurfaceView(Context context, ResolutionStrategy resolutionStrategy) {\r
+ super(context);\r
+ this.resolutionStrategy = resolutionStrategy;\r
+ }\r
+\r
+ public DefaultGLSurfaceView(Context context, AttributeSet attrs, ResolutionStrategy resolutionStrategy) {\r
+ super(context, attrs);\r
+ this.resolutionStrategy = resolutionStrategy;\r
+ }\r
+\r
+ @Override\r
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\r
+ ResolutionStrategy.MeasuredDimension measures = resolutionStrategy.calcMeasures(widthMeasureSpec, heightMeasureSpec);\r
+ setMeasuredDimension(measures.width, measures.height);\r
+ }\r
+}\r
--- /dev/null
+package com.badlogic.gdx.backends.android.surfaceview;\r
+\r
+import android.view.View;\r
+\r
+public class FillResolutionStrategy implements ResolutionStrategy {\r
+\r
+\r
+ @Override\r
+ public MeasuredDimension calcMeasures(int widthMeasureSpec, int heightMeasureSpec) {\r
+\r
+ final int width = View.MeasureSpec.getSize(widthMeasureSpec);\r
+ final int height = View.MeasureSpec.getSize(heightMeasureSpec);\r
+\r
+ return new MeasuredDimension(width, height);\r
+ }\r
+}\r
--- /dev/null
+package com.badlogic.gdx.backends.android.surfaceview;\r
+\r
+public class FixedResolutionStrategy implements ResolutionStrategy {\r
+\r
+ private final int width;\r
+ private final int height;\r
+\r
+ public FixedResolutionStrategy(int width, int height) {\r
+ this.width = width;\r
+ this.height = height;\r
+ }\r
+\r
+ @Override\r
+ public MeasuredDimension calcMeasures(int widthMeasureSpec, int heightMeasureSpec) {\r
+ return new MeasuredDimension(width, height);\r
+ }\r
+}\r
* governing permissions and limitations under the License.
*/
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-
import android.content.Context;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.util.Log;
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+
/**
* A simple GLSurfaceView sub-class that demonstrate how to perform OpenGL ES 2.0 rendering into a GL Surface. Note the following
* important details:
- *
+ * <p/>
* - The class must use a custom context factory to enable 2.0 rendering. See ContextFactory class definition below.
- *
+ * <p/>
* - The class must use a custom EGLConfigChooser to be able to select an EGLConfig that supports 2.0. This is done by providing a
* config specification to eglChooseConfig() that has the attribute EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT
* flag set. See ConfigChooser class definition below.
- *
+ * <p/>
* - The class must select the surface's format, then choose an EGLConfig that matches it exactly (with regards to
* red/green/blue/alpha channels bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
*/
public class GLSurfaceView20 extends GLSurfaceView {
- static String TAG = "GL2JNIView";
- private static final boolean DEBUG = false;
-
- public GLSurfaceView20 (Context context) {
- super(context);
- init(false, 16, 0);
- }
-
- public GLSurfaceView20 (Context context, boolean translucent, int depth, int stencil) {
- super(context);
- init(translucent, depth, stencil);
- }
-
- private void init (boolean translucent, int depth, int stencil) {
-
- /*
- * By default, GLSurfaceView() creates a RGB_565 opaque surface. If we want a translucent one, we should change the
- * surface's format here, using PixelFormat.TRANSLUCENT for GL Surfaces is interpreted as any 32-bit surface with alpha by
- * SurfaceFlinger.
- */
- if (translucent) {
- this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
- }
-
- /*
- * Setup the context factory for 2.0 rendering. See ContextFactory class definition below
- */
- setEGLContextFactory(new ContextFactory());
-
- /*
- * We need to choose an EGLConfig that matches the format of our surface exactly. This is going to be done in our custom
- * config chooser. See ConfigChooser class definition below.
- */
- setEGLConfigChooser(translucent ? new ConfigChooser(8, 8, 8, 8, depth, stencil) : new ConfigChooser(5, 6, 5, 0, depth,
- stencil));
-
- /* Set the renderer responsible for frame rendering */
- }
-
- static class ContextFactory implements GLSurfaceView.EGLContextFactory {
- private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-
- public EGLContext createContext (EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
- Log.w(TAG, "creating OpenGL ES 2.0 context");
- checkEglError("Before eglCreateContext", egl);
- int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
- EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
- checkEglError("After eglCreateContext", egl);
- return context;
- }
-
- public void destroyContext (EGL10 egl, EGLDisplay display, EGLContext context) {
- egl.eglDestroyContext(display, context);
- }
- }
-
- static void checkEglError (String prompt, EGL10 egl) {
- int error;
- while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
- Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
- }
- }
-
- private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
-
- public ConfigChooser (int r, int g, int b, int a, int depth, int stencil) {
- mRedSize = r;
- mGreenSize = g;
- mBlueSize = b;
- mAlphaSize = a;
- mDepthSize = depth;
- mStencilSize = stencil;
- }
-
- /*
- * This EGL config specification is used to specify 2.0 rendering. We use a minimum size of 4 bits for red/green/blue, but
- * will perform actual matching in chooseConfig() below.
- */
- private static int EGL_OPENGL_ES2_BIT = 4;
- private static int[] s_configAttribs2 = {EGL10.EGL_RED_SIZE, 4, EGL10.EGL_GREEN_SIZE, 4, EGL10.EGL_BLUE_SIZE, 4,
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE};
-
- public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display) {
-
- /*
- * Get the number of minimally matching EGL configurations
- */
- int[] num_config = new int[1];
- egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
-
- int numConfigs = num_config[0];
-
- if (numConfigs <= 0) {
- throw new IllegalArgumentException("No configs match configSpec");
- }
-
- /*
- * Allocate then read the array of minimally matching EGL configs
- */
- EGLConfig[] configs = new EGLConfig[numConfigs];
- egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
-
- if (DEBUG) {
- printConfigs(egl, display, configs);
- }
- /*
- * Now return the "best" one
- */
- return chooseConfig(egl, display, configs);
- }
-
- public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
- for (EGLConfig config : configs) {
- int d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);
- int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);
-
- // We need at least mDepthSize and mStencilSize bits
- if (d < mDepthSize || s < mStencilSize) continue;
-
- // We want an *exact* match for red/green/blue/alpha
- int r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);
- int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);
- int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);
- int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);
-
- if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize) return config;
- }
- return null;
- }
-
- private int findConfigAttrib (EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue) {
-
- if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
- return mValue[0];
- }
- return defaultValue;
- }
-
- private void printConfigs (EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
- int numConfigs = configs.length;
- Log.w(TAG, String.format("%d configurations", numConfigs));
- for (int i = 0; i < numConfigs; i++) {
- Log.w(TAG, String.format("Configuration %d:\n", i));
- printConfig(egl, display, configs[i]);
- }
- }
-
- private void printConfig (EGL10 egl, EGLDisplay display, EGLConfig config) {
- int[] attributes = {EGL10.EGL_BUFFER_SIZE, EGL10.EGL_ALPHA_SIZE, EGL10.EGL_BLUE_SIZE, EGL10.EGL_GREEN_SIZE,
- EGL10.EGL_RED_SIZE, EGL10.EGL_DEPTH_SIZE, EGL10.EGL_STENCIL_SIZE, EGL10.EGL_CONFIG_CAVEAT, EGL10.EGL_CONFIG_ID,
- EGL10.EGL_LEVEL, EGL10.EGL_MAX_PBUFFER_HEIGHT, EGL10.EGL_MAX_PBUFFER_PIXELS, EGL10.EGL_MAX_PBUFFER_WIDTH,
- EGL10.EGL_NATIVE_RENDERABLE, EGL10.EGL_NATIVE_VISUAL_ID, EGL10.EGL_NATIVE_VISUAL_TYPE,
- 0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
- EGL10.EGL_SAMPLES, EGL10.EGL_SAMPLE_BUFFERS, EGL10.EGL_SURFACE_TYPE, EGL10.EGL_TRANSPARENT_TYPE,
- EGL10.EGL_TRANSPARENT_RED_VALUE, EGL10.EGL_TRANSPARENT_GREEN_VALUE, EGL10.EGL_TRANSPARENT_BLUE_VALUE, 0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
- 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
- 0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
- 0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
- EGL10.EGL_LUMINANCE_SIZE, EGL10.EGL_ALPHA_MASK_SIZE, EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RENDERABLE_TYPE, 0x3042 // EGL10.EGL_CONFORMANT
- };
- String[] names = {"EGL_BUFFER_SIZE", "EGL_ALPHA_SIZE", "EGL_BLUE_SIZE", "EGL_GREEN_SIZE", "EGL_RED_SIZE",
- "EGL_DEPTH_SIZE", "EGL_STENCIL_SIZE", "EGL_CONFIG_CAVEAT", "EGL_CONFIG_ID", "EGL_LEVEL", "EGL_MAX_PBUFFER_HEIGHT",
- "EGL_MAX_PBUFFER_PIXELS", "EGL_MAX_PBUFFER_WIDTH", "EGL_NATIVE_RENDERABLE", "EGL_NATIVE_VISUAL_ID",
- "EGL_NATIVE_VISUAL_TYPE", "EGL_PRESERVED_RESOURCES", "EGL_SAMPLES", "EGL_SAMPLE_BUFFERS", "EGL_SURFACE_TYPE",
- "EGL_TRANSPARENT_TYPE", "EGL_TRANSPARENT_RED_VALUE", "EGL_TRANSPARENT_GREEN_VALUE", "EGL_TRANSPARENT_BLUE_VALUE",
- "EGL_BIND_TO_TEXTURE_RGB", "EGL_BIND_TO_TEXTURE_RGBA", "EGL_MIN_SWAP_INTERVAL", "EGL_MAX_SWAP_INTERVAL",
- "EGL_LUMINANCE_SIZE", "EGL_ALPHA_MASK_SIZE", "EGL_COLOR_BUFFER_TYPE", "EGL_RENDERABLE_TYPE", "EGL_CONFORMANT"};
- int[] value = new int[1];
- for (int i = 0; i < attributes.length; i++) {
- int attribute = attributes[i];
- String name = names[i];
- if (egl.eglGetConfigAttrib(display, config, attribute, value)) {
- Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
- } else {
- // Log.w(TAG, String.format(" %s: failed\n", name));
- while (egl.eglGetError() != EGL10.EGL_SUCCESS)
- ;
- }
- }
- }
-
- // Subclasses can adjust these values:
- protected int mRedSize;
- protected int mGreenSize;
- protected int mBlueSize;
- protected int mAlphaSize;
- protected int mDepthSize;
- protected int mStencilSize;
- private int[] mValue = new int[1];
- }
+ static String TAG = "GL2JNIView";
+ private static final boolean DEBUG = false;
+
+ final ResolutionStrategy resolutionStrategy;
+
+ public GLSurfaceView20(Context context, ResolutionStrategy resolutionStrategy) {
+ super(context);
+ this.resolutionStrategy = resolutionStrategy;
+ init(false, 16, 0);
+ }
+
+ public GLSurfaceView20(Context context, boolean translucent, int depth, int stencil, ResolutionStrategy resolutionStrategy) {
+ super(context);
+ this.resolutionStrategy = resolutionStrategy;
+ init(translucent, depth, stencil);
+
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ ResolutionStrategy.MeasuredDimension measures = resolutionStrategy.calcMeasures(widthMeasureSpec, heightMeasureSpec);
+ setMeasuredDimension(measures.width, measures.height);
+ }
+
+ private void init(boolean translucent, int depth, int stencil) {
+
+ /*
+ * By default, GLSurfaceView() creates a RGB_565 opaque surface. If we want a translucent one, we should change the
+ * surface's format here, using PixelFormat.TRANSLUCENT for GL Surfaces is interpreted as any 32-bit surface with alpha by
+ * SurfaceFlinger.
+ */
+ if (translucent) {
+ this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
+ }
+
+ /*
+ * Setup the context factory for 2.0 rendering. See ContextFactory class definition below
+ */
+ setEGLContextFactory(new ContextFactory());
+
+ /*
+ * We need to choose an EGLConfig that matches the format of our surface exactly. This is going to be done in our custom
+ * config chooser. See ConfigChooser class definition below.
+ */
+ setEGLConfigChooser(translucent ? new ConfigChooser(8, 8, 8, 8, depth, stencil) : new ConfigChooser(5, 6, 5, 0, depth,
+ stencil));
+
+ /* Set the renderer responsible for frame rendering */
+ }
+
+
+ static class ContextFactory implements GLSurfaceView.EGLContextFactory {
+ private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+
+ public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
+ Log.w(TAG, "creating OpenGL ES 2.0 context");
+ checkEglError("Before eglCreateContext", egl);
+ int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
+ EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+ checkEglError("After eglCreateContext", egl);
+ return context;
+ }
+
+ public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
+ egl.eglDestroyContext(display, context);
+ }
+ }
+
+ static void checkEglError(String prompt, EGL10 egl) {
+ int error;
+ while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
+ Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
+ }
+ }
+
+ private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
+
+ public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
+ mRedSize = r;
+ mGreenSize = g;
+ mBlueSize = b;
+ mAlphaSize = a;
+ mDepthSize = depth;
+ mStencilSize = stencil;
+ }
+
+ /*
+ * This EGL config specification is used to specify 2.0 rendering. We use a minimum size of 4 bits for red/green/blue, but
+ * will perform actual matching in chooseConfig() below.
+ */
+ private static int EGL_OPENGL_ES2_BIT = 4;
+ private static int[] s_configAttribs2 = {EGL10.EGL_RED_SIZE, 4, EGL10.EGL_GREEN_SIZE, 4, EGL10.EGL_BLUE_SIZE, 4,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE};
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+
+ /*
+ * Get the number of minimally matching EGL configurations
+ */
+ int[] num_config = new int[1];
+ egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
+
+ int numConfigs = num_config[0];
+
+ if (numConfigs <= 0) {
+ throw new IllegalArgumentException("No configs match configSpec");
+ }
+
+ /*
+ * Allocate then read the array of minimally matching EGL configs
+ */
+ EGLConfig[] configs = new EGLConfig[numConfigs];
+ egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
+
+ if (DEBUG) {
+ printConfigs(egl, display, configs);
+ }
+ /*
+ * Now return the "best" one
+ */
+ return chooseConfig(egl, display, configs);
+ }
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
+ for (EGLConfig config : configs) {
+ int d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);
+ int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);
+
+ // We need at least mDepthSize and mStencilSize bits
+ if (d < mDepthSize || s < mStencilSize) continue;
+
+ // We want an *exact* match for red/green/blue/alpha
+ int r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);
+ int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);
+ int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);
+ int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);
+
+ if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize) return config;
+ }
+ return null;
+ }
+
+ private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue) {
+
+ if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
+ return mValue[0];
+ }
+ return defaultValue;
+ }
+
+ private void printConfigs(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
+ int numConfigs = configs.length;
+ Log.w(TAG, String.format("%d configurations", numConfigs));
+ for (int i = 0; i < numConfigs; i++) {
+ Log.w(TAG, String.format("Configuration %d:\n", i));
+ printConfig(egl, display, configs[i]);
+ }
+ }
+
+ private void printConfig(EGL10 egl, EGLDisplay display, EGLConfig config) {
+ int[] attributes = {EGL10.EGL_BUFFER_SIZE, EGL10.EGL_ALPHA_SIZE, EGL10.EGL_BLUE_SIZE, EGL10.EGL_GREEN_SIZE,
+ EGL10.EGL_RED_SIZE, EGL10.EGL_DEPTH_SIZE, EGL10.EGL_STENCIL_SIZE, EGL10.EGL_CONFIG_CAVEAT, EGL10.EGL_CONFIG_ID,
+ EGL10.EGL_LEVEL, EGL10.EGL_MAX_PBUFFER_HEIGHT, EGL10.EGL_MAX_PBUFFER_PIXELS, EGL10.EGL_MAX_PBUFFER_WIDTH,
+ EGL10.EGL_NATIVE_RENDERABLE, EGL10.EGL_NATIVE_VISUAL_ID, EGL10.EGL_NATIVE_VISUAL_TYPE,
+ 0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
+ EGL10.EGL_SAMPLES, EGL10.EGL_SAMPLE_BUFFERS, EGL10.EGL_SURFACE_TYPE, EGL10.EGL_TRANSPARENT_TYPE,
+ EGL10.EGL_TRANSPARENT_RED_VALUE, EGL10.EGL_TRANSPARENT_GREEN_VALUE, EGL10.EGL_TRANSPARENT_BLUE_VALUE, 0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
+ 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
+ 0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
+ 0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
+ EGL10.EGL_LUMINANCE_SIZE, EGL10.EGL_ALPHA_MASK_SIZE, EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RENDERABLE_TYPE, 0x3042 // EGL10.EGL_CONFORMANT
+ };
+ String[] names = {"EGL_BUFFER_SIZE", "EGL_ALPHA_SIZE", "EGL_BLUE_SIZE", "EGL_GREEN_SIZE", "EGL_RED_SIZE",
+ "EGL_DEPTH_SIZE", "EGL_STENCIL_SIZE", "EGL_CONFIG_CAVEAT", "EGL_CONFIG_ID", "EGL_LEVEL", "EGL_MAX_PBUFFER_HEIGHT",
+ "EGL_MAX_PBUFFER_PIXELS", "EGL_MAX_PBUFFER_WIDTH", "EGL_NATIVE_RENDERABLE", "EGL_NATIVE_VISUAL_ID",
+ "EGL_NATIVE_VISUAL_TYPE", "EGL_PRESERVED_RESOURCES", "EGL_SAMPLES", "EGL_SAMPLE_BUFFERS", "EGL_SURFACE_TYPE",
+ "EGL_TRANSPARENT_TYPE", "EGL_TRANSPARENT_RED_VALUE", "EGL_TRANSPARENT_GREEN_VALUE", "EGL_TRANSPARENT_BLUE_VALUE",
+ "EGL_BIND_TO_TEXTURE_RGB", "EGL_BIND_TO_TEXTURE_RGBA", "EGL_MIN_SWAP_INTERVAL", "EGL_MAX_SWAP_INTERVAL",
+ "EGL_LUMINANCE_SIZE", "EGL_ALPHA_MASK_SIZE", "EGL_COLOR_BUFFER_TYPE", "EGL_RENDERABLE_TYPE", "EGL_CONFORMANT"};
+ int[] value = new int[1];
+ for (int i = 0; i < attributes.length; i++) {
+ int attribute = attributes[i];
+ String name = names[i];
+ if (egl.eglGetConfigAttrib(display, config, attribute, value)) {
+ Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
+ } else {
+ // Log.w(TAG, String.format(" %s: failed\n", name));
+ while (egl.eglGetError() != EGL10.EGL_SUCCESS)
+ ;
+ }
+ }
+ }
+
+ // Subclasses can adjust these values:
+ protected int mRedSize;
+ protected int mGreenSize;
+ protected int mBlueSize;
+ protected int mAlphaSize;
+ protected int mDepthSize;
+ protected int mStencilSize;
+ private int[] mValue = new int[1];
+ }
}
*/\r
public final static int DEBUG_LOG_GL_CALLS = 2;\r
\r
+ final ResolutionStrategy resolutionStrategy;\r
+\r
/**\r
* Standard View constructor. In order to render something, you must call {@link #setRenderer} to register a renderer.\r
*/\r
- public GLSurfaceViewCupcake (Context context) {\r
+ public GLSurfaceViewCupcake (Context context, ResolutionStrategy resolutionStrategy) {\r
super(context);\r
+ this.resolutionStrategy = resolutionStrategy;\r
init();\r
}\r
\r
/**\r
* Standard View constructor. In order to render something, you must call {@link #setRenderer} to register a renderer.\r
*/\r
- public GLSurfaceViewCupcake (Context context, AttributeSet attrs) {\r
+ public GLSurfaceViewCupcake (Context context, AttributeSet attrs, ResolutionStrategy resolutionStrategy) {\r
super(context, attrs);\r
+ this.resolutionStrategy = resolutionStrategy;\r
init();\r
}\r
\r
+\r
+ @Override\r
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\r
+ ResolutionStrategy.MeasuredDimension measures = resolutionStrategy.calcMeasures(widthMeasureSpec, heightMeasureSpec);\r
+ setMeasuredDimension(measures.width, measures.height);\r
+ }\r
+\r
private void init () {\r
// Install a SurfaceHolder.Callback so we get notified when the\r
// underlying surface is created and destroyed\r
--- /dev/null
+package com.badlogic.gdx.backends.android.surfaceview;\r
+\r
+import android.view.View;\r
+\r
+public class RatioResolutionStrategy implements ResolutionStrategy {\r
+\r
+ private final float ratio;\r
+\r
+ public RatioResolutionStrategy(float ratio) {\r
+ this.ratio = ratio;\r
+ }\r
+\r
+ public RatioResolutionStrategy(final float width, final float height) {\r
+ this.ratio = width / height;\r
+ }\r
+\r
+ @Override\r
+ public MeasuredDimension calcMeasures(int widthMeasureSpec, int heightMeasureSpec) {\r
+\r
+ final int specWidth = View.MeasureSpec.getSize(widthMeasureSpec);\r
+ final int specHeight = View.MeasureSpec.getSize(heightMeasureSpec);\r
+\r
+ final float desiredRatio = ratio;\r
+ final float realRatio = (float) specWidth / specHeight;\r
+\r
+ int width;\r
+ int height;\r
+ if (realRatio < desiredRatio) {\r
+ width = specWidth;\r
+ height = Math.round(width / desiredRatio);\r
+ } else {\r
+ height = specHeight;\r
+ width = Math.round(height * desiredRatio);\r
+ }\r
+\r
+ return new MeasuredDimension(width, height);\r
+ }\r
+}\r
--- /dev/null
+package com.badlogic.gdx.backends.android.surfaceview;\r
+\r
+public interface ResolutionStrategy {\r
+\r
+\r
+ public MeasuredDimension calcMeasures( final int widthMeasureSpec, final int heightMeasureSpec);\r
+\r
+\r
+ public static class MeasuredDimension {\r
+ public final int width;\r
+ public final int height;\r
+\r
+ public MeasuredDimension(int width, int height) {\r
+ this.width = width;\r
+ this.height = height;\r
+ }\r
+\r
+ }\r
+\r
+\r
+\r
+\r
+}\r