diff --git a/alienblaster/project/src/GLSurfaceView_SDL.java b/alienblaster/project/src/GLSurfaceView_SDL.java index 6567ddeff..4c9067afb 100644 --- a/alienblaster/project/src/GLSurfaceView_SDL.java +++ b/alienblaster/project/src/GLSurfaceView_SDL.java @@ -897,6 +897,7 @@ public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Call mEglHelper = new EglHelper(); // mEglHelper.start(); mNeedStart = true; + mSizeChanged = true; SwapBuffers(); SwapBuffers(); @@ -955,6 +956,7 @@ public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Call mEglHelper.start(); tellRendererSurfaceCreated = true; changed = true; + mNeedStart = false; } if (changed) { mGL = (GL10) mEglHelper.createSurface(getHolder()); diff --git a/alienblaster/project/src_1.6/GLSurfaceView_SDL.java b/alienblaster/project/src_1.6/GLSurfaceView_SDL.java deleted file mode 100644 index 6567ddeff..000000000 --- a/alienblaster/project/src_1.6/GLSurfaceView_SDL.java +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This is GLSurfaceView class ripped out of Android 2.1 sources, - fixed with a hammer and rasp to work with libSDL port */ - -// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount -package com.demo.glxgears; - -import java.io.Writer; -import java.util.ArrayList; -import java.util.concurrent.Semaphore; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGL11; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL; -import javax.microedition.khronos.opengles.GL10; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - -/** - * An implementation of SurfaceView that uses the dedicated surface for - * displaying OpenGL rendering. - *

- * A GLSurfaceView provides the following features: - *

- *

- * - *

Using GLSurfaceView

- *

- * Typically you use GLSurfaceView by subclassing it and overriding one or more of the - * View system input event methods. If your application does not need to override event - * methods then GLSurfaceView can be used as-is. For the most part - * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. - * For example, unlike a regular View, drawing is delegated to a separate Renderer object which - * is registered with the GLSurfaceView - * using the {@link #setRenderer(Renderer)} call. - *

- *

Initializing GLSurfaceView

- * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}. - * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or - * more of these methods before calling setRenderer: - * - *

- *

Choosing an EGL Configuration

- * A given Android device may support multiple possible types of drawing surfaces. - * The available surfaces may differ in how may channels of data are present, as - * well as how many bits are allocated to each channel. Therefore, the first thing - * GLSurfaceView has to do when starting to render is choose what type of surface to use. - *

- * By default GLSurfaceView chooses an available surface that's closest to a 16-bit R5G6B5 surface - * with a 16-bit depth buffer and no stencil. If you would prefer a different surface (for example, - * if you do not need a depth buffer) you can override the default behavior by calling one of the - * setEGLConfigChooser methods. - *

- *

Debug Behavior

- * You can optionally modify the behavior of GLSurfaceView by calling - * one or more of the debugging methods {@link #setDebugFlags(int)}, - * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but - * typically they are called before setRenderer so that they take effect immediately. - *

- *

Setting a Renderer

- * Finally, you must call {@link #setRenderer} to register a {@link Renderer}. - * The renderer is - * responsible for doing the actual OpenGL rendering. - *

- *

Rendering Mode

- * Once the renderer is set, you can control whether the renderer draws - * continuously or on-demand by calling - * {@link #setRenderMode}. The default is continuous rendering. - *

- *

Activity Life-cycle

- * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients - * are required to call {@link #onPause()} when the activity pauses and - * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to - * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate - * the OpenGL display. - *

- *

Handling events

- *

- * To handle an event you will typically subclass GLSurfaceView and override the - * appropriate method, just as you would with any other View. However, when handling - * the event, you may need to communicate with the Renderer object - * that's running in the rendering thread. You can do this using any - * standard Java cross-thread communication mechanism. In addition, - * one relatively easy way to communicate with your renderer is - * to call - * {@link #queueEvent(Runnable)}. For example: - *

- * class MyGLSurfaceView extends GLSurfaceView {
- *
- *     private MyRenderer mMyRenderer;
- *
- *     public void start() {
- *         mMyRenderer = ...;
- *         setRenderer(mMyRenderer);
- *     }
- *
- *     public boolean onKeyDown(int keyCode, KeyEvent event) {
- *         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- *             queueEvent(new Runnable() {
- *                 // This method will be called on the rendering
- *                 // thread:
- *                 public void run() {
- *                     mMyRenderer.handleDpadCenter();
- *                 }});
- *             return true;
- *         }
- *         return super.onKeyDown(keyCode, event);
- *     }
- * }
- * 
- * - */ -public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Callback { - /** - * The renderer only renders - * when the surface is created, or when {@link #requestRender} is called. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - */ - public final static int RENDERMODE_WHEN_DIRTY = 0; - /** - * The renderer is called - * continuously to re-render the scene. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - * @see #requestRender() - */ - public final static int RENDERMODE_CONTINUOUSLY = 1; - - /** - * Check glError() after every GL call and throw an exception if glError indicates - * that an error has occurred. This can be used to help track down which OpenGL ES call - * is causing an error. - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - public final static int DEBUG_CHECK_GL_ERROR = 1; - - /** - * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - public final static int DEBUG_LOG_GL_CALLS = 2; - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLSurfaceView_SDL(Context context) { - super(context); - init(); - } - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLSurfaceView_SDL(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - private void init() { - // Install a SurfaceHolder.Callback so we get notified when the - // underlying surface is created and destroyed - SurfaceHolder holder = getHolder(); - holder.addCallback(this); - holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); - } - - /** - * Set the glWrapper. If the glWrapper is not null, its - * {@link GLWrapper#wrap(GL)} method is called - * whenever a surface is created. A GLWrapper can be used to wrap - * the GL object that's passed to the renderer. Wrapping a GL - * object enables examining and modifying the behavior of the - * GL calls made by the renderer. - *

- * Wrapping is typically used for debugging purposes. - *

- * The default value is null. - * @param glWrapper the new GLWrapper - */ - public void setGLWrapper(GLWrapper glWrapper) { - mGLWrapper = glWrapper; - } - - /** - * Set the debug flags to a new value. The value is - * constructed by OR-together zero or more - * of the DEBUG_CHECK_* constants. The debug flags take effect - * whenever a surface is created. The default value is zero. - * @param debugFlags the new debug flags - * @see #DEBUG_CHECK_GL_ERROR - * @see #DEBUG_LOG_GL_CALLS - */ - public void setDebugFlags(int debugFlags) { - mDebugFlags = debugFlags; - } - - /** - * Get the current value of the debug flags. - * @return the current value of the debug flags. - */ - public int getDebugFlags() { - return mDebugFlags; - } - - /** - * Set the renderer associated with this view. Also starts the thread that - * will call the renderer, which in turn causes the rendering to start. - *

This method should be called once and only once in the life-cycle of - * a GLSurfaceView. - *

The following GLSurfaceView methods can only be called before - * setRenderer is called: - *

- *

- * The following GLSurfaceView methods can only be called after - * setRenderer is called: - *

- * - * @param renderer the renderer to use to perform OpenGL drawing. - */ - public void setRenderer(Renderer renderer) { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - if (mEGLConfigChooser == null) { - mEGLConfigChooser = new SimpleEGLConfigChooser(true); - } - mGLThread = new GLThread(renderer); - mGLThread.start(); - } - - /** - * Install a custom EGLConfigChooser. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * @param configChooser - */ - public void setEGLConfigChooser(EGLConfigChooser configChooser) { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - mEGLConfigChooser = configChooser; - } - - /** - * Install a config chooser which will choose a config - * as close to 16-bit RGB as possible, with or without an optional depth - * buffer as close to 16-bits as possible. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * - * @param needDepth - */ - public void setEGLConfigChooser(boolean needDepth) { - setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); - } - - /** - * Install a config chooser which will choose a config - * with at least the specified component sizes, and as close - * to the specified component sizes as possible. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * - */ - public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, - blueSize, alphaSize, depthSize, stencilSize)); - } - /** - * Set the rendering mode. When renderMode is - * RENDERMODE_CONTINUOUSLY, the renderer is called - * repeatedly to re-render the scene. When renderMode - * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface - * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. - *

- * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance - * by allowing the GPU and CPU to idle when the view does not need to be updated. - *

- * This method can only be called after {@link #setRenderer(Renderer)} - * - * @param renderMode one of the RENDERMODE_X constants - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - public void setRenderMode(int renderMode) { - mGLThread.setRenderMode(renderMode); - } - - /** - * Get the current rendering mode. May be called - * from any thread. Must not be called before a renderer has been set. - * @return the current rendering mode. - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - public int getRenderMode() { - return mGLThread.getRenderMode(); - } - - /** - * Request that the renderer render a frame. - * This method is typically used when the render mode has been set to - * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. - * May be called - * from any thread. Must not be called before a renderer has been set. - */ - public void requestRender() { - mGLThread.requestRender(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceCreated(SurfaceHolder holder) { - mGLThread.surfaceCreated(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceDestroyed(SurfaceHolder holder) { - // Surface will be destroyed when we return - mGLThread.surfaceDestroyed(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - mGLThread.onWindowResize(w, h); - } - - /** - * Inform the view that the activity is paused. The owner of this view must - * call this method when the activity is paused. Calling this method will - * pause the rendering thread. - * Must not be called before a renderer has been set. - */ - public void onPause() { - mGLThread.onPause(); - } - - /** - * Inform the view that the activity is resumed. The owner of this view must - * call this method when the activity is resumed. Calling this method will - * recreate the OpenGL display and resume the rendering - * thread. - * Must not be called before a renderer has been set. - */ - public void onResume() { - mGLThread.onResume(); - } - - /** - * Queue a runnable to be run on the GL rendering thread. This can be used - * to communicate with the Renderer on the rendering thread. - * Must not be called before a renderer has been set. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - mGLThread.queueEvent(r); - } - - /** - * This method is used as part of the View class and is not normally - * called or subclassed by clients of GLSurfaceView. - * Must not be called before a renderer has been set. - */ - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - mGLThread.requestExitAndWait(); - } - - // ---------------------------------------------------------------------- - - /** - * An interface used to wrap a GL interface. - *

Typically - * used for implementing debugging and tracing on top of the default - * GL interface. You would typically use this by creating your own class - * that implemented all the GL methods by delegating to another GL instance. - * Then you could add your own behavior before or after calling the - * delegate. All the GLWrapper would do was instantiate and return the - * wrapper GL instance: - *

-     * class MyGLWrapper implements GLWrapper {
-     *     GL wrap(GL gl) {
-     *         return new MyGLImplementation(gl);
-     *     }
-     *     static class MyGLImplementation implements GL,GL10,GL11,... {
-     *         ...
-     *     }
-     * }
-     * 
- * @see #setGLWrapper(GLWrapper) - */ - public interface GLWrapper { - /** - * Wraps a gl interface in another gl interface. - * @param gl a GL interface that is to be wrapped. - * @return either the input argument or another GL object that wraps the input argument. - */ - GL wrap(GL gl); - } - - /** - * A generic renderer interface. - *

- * The renderer is responsible for making OpenGL calls to render a frame. - *

- * GLSurfaceView clients typically create their own classes that implement - * this interface, and then call {@link GLSurfaceView#setRenderer} to - * register the renderer with the GLSurfaceView. - *

- *

Threading

- * The renderer will be called on a separate thread, so that rendering - * performance is decoupled from the UI thread. Clients typically need to - * communicate with the renderer from the UI thread, because that's where - * input events are received. Clients can communicate using any of the - * standard Java techniques for cross-thread communication, or they can - * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. - *

- *

EGL Context Lost

- * There are situations where the EGL rendering context will be lost. This - * typically happens when device wakes up after going to sleep. When - * the EGL context is lost, all OpenGL resources (such as textures) that are - * associated with that context will be automatically deleted. In order to - * keep rendering correctly, a renderer must recreate any lost resources - * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method - * is a convenient place to do this. - * - * - * @see #setRenderer(Renderer) - */ - public static interface SwapBuffersCallback { - public boolean SwapBuffers(); - } - - public static abstract class Renderer { - /** - * Called when the surface is created or recreated. - *

- * Called when the rendering thread - * starts and whenever the EGL context is lost. The context will typically - * be lost when the Android device awakes after going to sleep. - *

- * Since this method is called at the beginning of rendering, as well as - * every time the EGL context is lost, this method is a convenient place to put - * code to create resources that need to be created when the rendering - * starts, and that need to be recreated when the EGL context is lost. - * Textures are an example of a resource that you might want to create - * here. - *

- * Note that when the EGL context is lost, all OpenGL resources associated - * with that context will be automatically deleted. You do not need to call - * the corresponding "glDelete" methods such as glDeleteTextures to - * manually delete these lost resources. - *

- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param config the EGLConfig of the created surface. Can be used - * to create matching pbuffers. - */ - public abstract void onSurfaceCreated(GL10 gl, EGLConfig config); - - /** - * Called when the surface changed size. - *

- * Called after the surface is created and whenever - * the OpenGL ES surface size changes. - *

- * Typically you will set your viewport here. If your camera - * is fixed then you could also set your projection matrix here: - *

-         * void onSurfaceChanged(GL10 gl, int width, int height) {
-         *     gl.glViewport(0, 0, width, height);
-         *     // for a fixed camera, set the projection too
-         *     float ratio = (float) width / height;
-         *     gl.glMatrixMode(GL10.GL_PROJECTION);
-         *     gl.glLoadIdentity();
-         *     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
-         * }
-         * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param width - * @param height - */ - public abstract void onSurfaceChanged(GL10 gl, int width, int height); - - /** - * Called to draw the current frame. - *

- * This method is responsible for drawing the current frame. - *

- * The implementation of this method typically looks like this: - *

-         * void onDrawFrame(GL10 gl) {
-         *     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
-         *     //... other gl calls to render the scene ...
-         * }
-         * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - */ - public abstract void onDrawFrame(GL10 gl); - - public boolean SwapBuffers() { - if( mSwapBuffersCallback != null ) - return mSwapBuffersCallback.SwapBuffers(); - return false; - } - - public void setSwapBuffersCallback( SwapBuffersCallback c ) { - mSwapBuffersCallback = c; - } - - private SwapBuffersCallback mSwapBuffersCallback = null; - } - - /** - * An interface for choosing an EGLConfig configuration from a list of - * potential configurations. - *

- * This interface must be implemented by clients wishing to call - * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} - */ - public interface EGLConfigChooser { - /** - * Choose a configuration from the list. Implementors typically - * implement this method by calling - * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the - * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. - * @param egl the EGL10 for the current display. - * @param display the current display. - * @return the chosen configuration. - */ - EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); - } - - private static abstract class BaseConfigChooser - implements EGLConfigChooser { - public BaseConfigChooser(int[] configSpec) { - mConfigSpec = configSpec; - } - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - int[] num_config = new int[1]; - egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config); - - int numConfigs = num_config[0]; - - if (numConfigs <= 0) { - throw new IllegalArgumentException( - "No configs match configSpec"); - } - - EGLConfig[] configs = new EGLConfig[numConfigs]; - egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, - num_config); - EGLConfig config = chooseConfig(egl, display, configs); - if (config == null) { - throw new IllegalArgumentException("No config chosen"); - } - return config; - } - - abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs); - - protected int[] mConfigSpec; - } - - private static class ComponentSizeChooser extends BaseConfigChooser { - public ComponentSizeChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - super(new int[] { - EGL10.EGL_RED_SIZE, redSize, - EGL10.EGL_GREEN_SIZE, greenSize, - EGL10.EGL_BLUE_SIZE, blueSize, - EGL10.EGL_ALPHA_SIZE, alphaSize, - EGL10.EGL_DEPTH_SIZE, depthSize, - EGL10.EGL_STENCIL_SIZE, stencilSize, - EGL10.EGL_NONE}); - mValue = new int[1]; - mRedSize = redSize; - mGreenSize = greenSize; - mBlueSize = blueSize; - mAlphaSize = alphaSize; - mDepthSize = depthSize; - mStencilSize = stencilSize; - } - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs) { - EGLConfig closestConfig = null; - int closestDistance = 1000; - for(EGLConfig config : configs) { - 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); - int d = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); - int s = findConfigAttrib(egl, display, config, - EGL10.EGL_STENCIL_SIZE, 0); - int distance = Math.abs(r - mRedSize) - + Math.abs(g - mGreenSize) - + Math.abs(b - mBlueSize) + Math.abs(a - mAlphaSize) - + Math.abs(d - mDepthSize) + Math.abs(s - mStencilSize); - if (distance < closestDistance) { - closestDistance = distance; - closestConfig = config; - } - } - return closestConfig; - } - - 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 int[] mValue; - // Subclasses can adjust these values: - protected int mRedSize; - protected int mGreenSize; - protected int mBlueSize; - protected int mAlphaSize; - protected int mDepthSize; - protected int mStencilSize; - } - - /** - * This class will choose a supported surface as close to - * RGB565 as possible, with or without a depth buffer. - * - */ - private static class SimpleEGLConfigChooser extends ComponentSizeChooser { - public SimpleEGLConfigChooser(boolean withDepthBuffer) { - super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0); - // Adjust target values. This way we'll accept a 4444 or - // 555 buffer if there's no 565 buffer available. - mRedSize = 5; - mGreenSize = 6; - mBlueSize = 5; - } - } - - /** - * An EGL helper class. - */ - - private class EglHelper { - public EglHelper() { - - } - - /** - * Initialize EGL for a given configuration spec. - * @param configSpec - */ - public void start(){ - /* - * Get an EGL instance - */ - mEgl = (EGL10) EGLContext.getEGL(); - - /* - * Get to the default display. - */ - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - /* - * We can now initialize EGL for that display - */ - int[] version = new int[2]; - mEgl.eglInitialize(mEglDisplay, version); - mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); - - /* - * Create an OpenGL ES context. This must be done only once, an - * OpenGL context is a somewhat heavy object. - */ - mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, - EGL10.EGL_NO_CONTEXT, null); - - mEglSurface = null; - } - - /* - * React to the creation of a new surface by creating and returning an - * OpenGL interface that renders to that surface. - */ - public GL createSurface(SurfaceHolder holder) { - /* - * The window size has changed, so we need to create a new - * surface. - */ - if (mEglSurface != null) { - - /* - * Unbind and destroy the old EGL surface, if - * there is one. - */ - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - mEgl.eglDestroySurface(mEglDisplay, mEglSurface); - } - - /* - * Create an EGL surface we can render into. - */ - mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, - mEglConfig, holder, null); - - /* - * Before we can issue GL commands, we need to make sure - * the context is current and bound to a surface. - */ - mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext); - - - GL gl = mEglContext.getGL(); - if (mGLWrapper != null) { - gl = mGLWrapper.wrap(gl); - } - - return gl; - } - - /** - * Display the current render surface. - * @return false if the context has been lost. - */ - public boolean swap() { - mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); - - /* - * Always check for EGL_CONTEXT_LOST, which means the context - * and all associated data were lost (For instance because - * the device went to sleep). We need to sleep until we - * get a new surface. - */ - return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST; - } - - public void finish() { - if (mEglSurface != null) { - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_CONTEXT); - mEgl.eglDestroySurface(mEglDisplay, mEglSurface); - mEglSurface = null; - } - if (mEglContext != null) { - mEgl.eglDestroyContext(mEglDisplay, mEglContext); - mEglContext = null; - } - if (mEglDisplay != null) { - mEgl.eglTerminate(mEglDisplay); - mEglDisplay = null; - } - } - - EGL10 mEgl; - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLConfig mEglConfig; - EGLContext mEglContext; - } - - /** - * A generic GL Thread. Takes care of initializing EGL and GL. Delegates - * to a Renderer instance to do the actual drawing. Can be configured to - * render continuously or on request. - * - */ - class GLThread extends Thread implements SwapBuffersCallback { - GLThread(Renderer renderer) { - super(); - mDone = false; - mWidth = 0; - mHeight = 0; - mRequestRender = true; - mRenderMode = RENDERMODE_CONTINUOUSLY; - mRenderer = renderer; - mRenderer.setSwapBuffersCallback(this); - setName("GLThread"); - } - - @Override - public void run() { - /* - * When the android framework launches a second instance of - * an activity, the new instance's onCreate() method may be - * called before the first instance returns from onDestroy(). - * - * This semaphore ensures that only one instance at a time - * accesses EGL. - */ - try { - sEglSemaphore.acquire(); - } catch (InterruptedException e) { - return; - } - - mEglHelper = new EglHelper(); - // mEglHelper.start(); - mNeedStart = true; - SwapBuffers(); - SwapBuffers(); - - mRenderer.onDrawFrame(mGL); - - mEglHelper.finish(); - - /* - synchronized (sGLThreadManager) { - stopEglLocked(); - } - sGLThreadManager.threadExiting(this); - */ - - sEglSemaphore.release(); - } - - public boolean SwapBuffers() { - - boolean tellRendererSurfaceCreated = false; - boolean tellRendererSurfaceChanged = false; - - /* - * This is our main activity thread's loop, we go until - * asked to quit. - */ - try { - - /* - * Update the asynchronous state (window size) - */ - int w, h; - boolean changed; - synchronized (this) { - Runnable r; - while ((r = getEvent()) != null) { - r.run(); - } - if (mPaused) { - mEglHelper.finish(); - mNeedStart = true; - } - while (needToWait()) { - wait(); - } - if (mDone) { - return false; - } - changed = mSizeChanged; - w = mWidth; - h = mHeight; - mSizeChanged = false; - mRequestRender = false; - } - if (mNeedStart) { - mEglHelper.start(); - tellRendererSurfaceCreated = true; - changed = true; - } - if (changed) { - mGL = (GL10) mEglHelper.createSurface(getHolder()); - tellRendererSurfaceChanged = true; - } - if (tellRendererSurfaceCreated) { - mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig); - tellRendererSurfaceCreated = false; - } - if (tellRendererSurfaceChanged) { - mRenderer.onSurfaceChanged(mGL, w, h); - tellRendererSurfaceChanged = false; - } - /* - * Once we're done with GL, we need to call swapBuffers() - * to instruct the system to display the rendered frame - */ - return mEglHelper.swap(); - - } catch (java.lang.InterruptedException e) { - return false; - } - } - - private boolean needToWait() { - if (mDone) { - return false; - } - - if (mPaused || (! mHasSurface)) { - return true; - } - - if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { - return false; - } - - return true; - } - - public void setRenderMode(int renderMode) { - if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { - throw new IllegalArgumentException("renderMode"); - } - synchronized(this) { - mRenderMode = renderMode; - if (renderMode == RENDERMODE_CONTINUOUSLY) { - notify(); - } - } - } - - public int getRenderMode() { - synchronized(this) { - return mRenderMode; - } - } - - public void requestRender() { - synchronized(this) { - mRequestRender = true; - notify(); - } - } - - public void surfaceCreated() { - synchronized(this) { - mHasSurface = true; - notify(); - } - } - - public void surfaceDestroyed() { - synchronized(this) { - mHasSurface = false; - notify(); - } - } - - public void onPause() { - synchronized (this) { - mPaused = true; - } - } - - public void onResume() { - synchronized (this) { - mPaused = false; - notify(); - } - } - - public void onWindowResize(int w, int h) { - synchronized (this) { - mWidth = w; - mHeight = h; - mSizeChanged = true; - notify(); - } - } - - public void requestExitAndWait() { - // don't call this from GLThread thread or it is a guaranteed - // deadlock! - synchronized(this) { - mDone = true; - notify(); - } - try { - join(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - - /** - * Queue an "event" to be run on the GL rendering thread. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - synchronized(this) { - mEventQueue.add(r); - } - } - - private Runnable getEvent() { - synchronized(this) { - if (mEventQueue.size() > 0) { - return mEventQueue.remove(0); - } - - } - return null; - } - - private boolean mDone; - private boolean mPaused; - private boolean mHasSurface; - private int mWidth; - private int mHeight; - private int mRenderMode; - private boolean mRequestRender; - private Renderer mRenderer; - private ArrayList mEventQueue = new ArrayList(); - private EglHelper mEglHelper; - private GL10 mGL = null; - private boolean mNeedStart = false; - } - - static class LogWriter extends Writer { - - @Override public void close() { - flushBuilder(); - } - - @Override public void flush() { - flushBuilder(); - } - - @Override public void write(char[] buf, int offset, int count) { - for(int i = 0; i < count; i++) { - char c = buf[offset + i]; - if ( c == '\n') { - flushBuilder(); - } - else { - mBuilder.append(c); - } - } - } - - private void flushBuilder() { - if (mBuilder.length() > 0) { - Log.v("GLSurfaceView", mBuilder.toString()); - mBuilder.delete(0, mBuilder.length()); - } - } - - private StringBuilder mBuilder = new StringBuilder(); - } - - private static final Semaphore sEglSemaphore = new Semaphore(1); - private boolean mSizeChanged = true; - - private GLThread mGLThread; - private EGLConfigChooser mEGLConfigChooser; - private GLWrapper mGLWrapper; - private int mDebugFlags; -} diff --git a/alienblaster/project/src_2.1/GLSurfaceView_SDL.java b/alienblaster/project/src_2.1/GLSurfaceView_SDL.java deleted file mode 100644 index 19f748108..000000000 --- a/alienblaster/project/src_2.1/GLSurfaceView_SDL.java +++ /dev/null @@ -1,1355 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This is GLSurfaceView class ripped out of Android 2.1 sources, - fixed with a hammer and rasp to work with libSDL port */ - -// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount -package de.schwardtnet.alienblaster; - -import java.io.Writer; -import java.util.ArrayList; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGL11; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL; -import javax.microedition.khronos.opengles.GL10; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - -/** - * An implementation of SurfaceView that uses the dedicated surface for - * displaying OpenGL rendering. - *

- * A GLSurfaceView provides the following features: - *

- *

- * - *

Using GLSurfaceView

- *

- * Typically you use GLSurfaceView by subclassing it and overriding one or more of the - * View system input event methods. If your application does not need to override event - * methods then GLSurfaceView can be used as-is. For the most part - * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. - * For example, unlike a regular View, drawing is delegated to a separate Renderer object which - * is registered with the GLSurfaceView - * using the {@link #setRenderer(Renderer)} call. - *

- *

Initializing GLSurfaceView

- * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}. - * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or - * more of these methods before calling setRenderer: - * - *

- *

Choosing an EGL Configuration

- * A given Android device may support multiple possible types of drawing surfaces. - * The available surfaces may differ in how may channels of data are present, as - * well as how many bits are allocated to each channel. Therefore, the first thing - * GLSurfaceView has to do when starting to render is choose what type of surface to use. - *

- * By default GLSurfaceView chooses an available surface that's closest to a 16-bit R5G6B5 surface - * with a 16-bit depth buffer and no stencil. If you would prefer a different surface (for example, - * if you do not need a depth buffer) you can override the default behavior by calling one of the - * setEGLConfigChooser methods. - *

- *

Debug Behavior

- * You can optionally modify the behavior of GLSurfaceView by calling - * one or more of the debugging methods {@link #setDebugFlags(int)}, - * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but - * typically they are called before setRenderer so that they take effect immediately. - *

- *

Setting a Renderer

- * Finally, you must call {@link #setRenderer} to register a {@link Renderer}. - * The renderer is - * responsible for doing the actual OpenGL rendering. - *

- *

Rendering Mode

- * Once the renderer is set, you can control whether the renderer draws - * continuously or on-demand by calling - * {@link #setRenderMode}. The default is continuous rendering. - *

- *

Activity Life-cycle

- * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients - * are required to call {@link #onPause()} when the activity pauses and - * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to - * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate - * the OpenGL display. - *

- *

Handling events

- *

- * To handle an event you will typically subclass GLSurfaceView and override the - * appropriate method, just as you would with any other View. However, when handling - * the event, you may need to communicate with the Renderer object - * that's running in the rendering thread. You can do this using any - * standard Java cross-thread communication mechanism. In addition, - * one relatively easy way to communicate with your renderer is - * to call - * {@link #queueEvent(Runnable)}. For example: - *

- * class MyGLSurfaceView extends GLSurfaceView {
- *
- *     private MyRenderer mMyRenderer;
- *
- *     public void start() {
- *         mMyRenderer = ...;
- *         setRenderer(mMyRenderer);
- *     }
- *
- *     public boolean onKeyDown(int keyCode, KeyEvent event) {
- *         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- *             queueEvent(new Runnable() {
- *                 // This method will be called on the rendering
- *                 // thread:
- *                 public void run() {
- *                     mMyRenderer.handleDpadCenter();
- *                 }});
- *             return true;
- *         }
- *         return super.onKeyDown(keyCode, event);
- *     }
- * }
- * 
- * - */ -public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Callback { - private final static boolean LOG_THREADS = false; - private final static boolean LOG_SURFACE = false; - private final static boolean LOG_RENDERER = false; - // Work-around for bug 2263168 - private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true; - /** - * The renderer only renders - * when the surface is created, or when {@link #requestRender} is called. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - */ - public final static int RENDERMODE_WHEN_DIRTY = 0; - /** - * The renderer is called - * continuously to re-render the scene. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - * @see #requestRender() - */ - public final static int RENDERMODE_CONTINUOUSLY = 1; - - /** - * Check glError() after every GL call and throw an exception if glError indicates - * that an error has occurred. This can be used to help track down which OpenGL ES call - * is causing an error. - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - public final static int DEBUG_CHECK_GL_ERROR = 1; - - /** - * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - public final static int DEBUG_LOG_GL_CALLS = 2; - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLSurfaceView_SDL(Context context) { - super(context); - init(); - } - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLSurfaceView_SDL(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - private void init() { - // Install a SurfaceHolder.Callback so we get notified when the - // underlying surface is created and destroyed - SurfaceHolder holder = getHolder(); - holder.addCallback(this); - } - - /** - * Set the glWrapper. If the glWrapper is not null, its - * {@link GLWrapper#wrap(GL)} method is called - * whenever a surface is created. A GLWrapper can be used to wrap - * the GL object that's passed to the renderer. Wrapping a GL - * object enables examining and modifying the behavior of the - * GL calls made by the renderer. - *

- * Wrapping is typically used for debugging purposes. - *

- * The default value is null. - * @param glWrapper the new GLWrapper - */ - public void setGLWrapper(GLWrapper glWrapper) { - mGLWrapper = glWrapper; - } - - /** - * Set the debug flags to a new value. The value is - * constructed by OR-together zero or more - * of the DEBUG_CHECK_* constants. The debug flags take effect - * whenever a surface is created. The default value is zero. - * @param debugFlags the new debug flags - * @see #DEBUG_CHECK_GL_ERROR - * @see #DEBUG_LOG_GL_CALLS - */ - public void setDebugFlags(int debugFlags) { - mDebugFlags = debugFlags; - } - - /** - * Get the current value of the debug flags. - * @return the current value of the debug flags. - */ - public int getDebugFlags() { - return mDebugFlags; - } - - /** - * Set the renderer associated with this view. Also starts the thread that - * will call the renderer, which in turn causes the rendering to start. - *

This method should be called once and only once in the life-cycle of - * a GLSurfaceView. - *

The following GLSurfaceView methods can only be called before - * setRenderer is called: - *

- *

- * The following GLSurfaceView methods can only be called after - * setRenderer is called: - *

- * - * @param renderer the renderer to use to perform OpenGL drawing. - */ - public void setRenderer(Renderer renderer) { - checkRenderThreadState(); - if (mEGLConfigChooser == null) { - mEGLConfigChooser = new SimpleEGLConfigChooser(true); - } - if (mEGLContextFactory == null) { - mEGLContextFactory = new DefaultContextFactory(); - } - if (mEGLWindowSurfaceFactory == null) { - mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); - } - mGLThread = new GLThread(renderer); - mGLThread.start(); - } - - /** - * Install a custom EGLContextFactory. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If this method is not called, then by default - * a context will be created with no shared context and - * with a null attribute list. - */ - public void setEGLContextFactory(EGLContextFactory factory) { - checkRenderThreadState(); - mEGLContextFactory = factory; - } - - /** - * Install a custom EGLWindowSurfaceFactory. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If this method is not called, then by default - * a window surface will be created with a null attribute list. - */ - public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { - checkRenderThreadState(); - mEGLWindowSurfaceFactory = factory; - } - - /** - * Install a custom EGLConfigChooser. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * @param configChooser - */ - public void setEGLConfigChooser(EGLConfigChooser configChooser) { - checkRenderThreadState(); - mEGLConfigChooser = configChooser; - } - - /** - * Install a config chooser which will choose a config - * as close to 16-bit RGB as possible, with or without an optional depth - * buffer as close to 16-bits as possible. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * - * @param needDepth - */ - public void setEGLConfigChooser(boolean needDepth) { - setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); - } - - /** - * Install a config chooser which will choose a config - * with at least the specified component sizes, and as close - * to the specified component sizes as possible. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * - */ - public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, - blueSize, alphaSize, depthSize, stencilSize)); - } - /** - * Set the rendering mode. When renderMode is - * RENDERMODE_CONTINUOUSLY, the renderer is called - * repeatedly to re-render the scene. When renderMode - * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface - * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. - *

- * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance - * by allowing the GPU and CPU to idle when the view does not need to be updated. - *

- * This method can only be called after {@link #setRenderer(Renderer)} - * - * @param renderMode one of the RENDERMODE_X constants - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - public void setRenderMode(int renderMode) { - mGLThread.setRenderMode(renderMode); - } - - /** - * Get the current rendering mode. May be called - * from any thread. Must not be called before a renderer has been set. - * @return the current rendering mode. - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - public int getRenderMode() { - return mGLThread.getRenderMode(); - } - - /** - * Request that the renderer render a frame. - * This method is typically used when the render mode has been set to - * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. - * May be called - * from any thread. Must not be called before a renderer has been set. - */ - public void requestRender() { - mGLThread.requestRender(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceCreated(SurfaceHolder holder) { - mGLThread.surfaceCreated(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceDestroyed(SurfaceHolder holder) { - // Surface will be destroyed when we return - mGLThread.surfaceDestroyed(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - mGLThread.onWindowResize(w, h); - } - - /** - * Inform the view that the activity is paused. The owner of this view must - * call this method when the activity is paused. Calling this method will - * pause the rendering thread. - * Must not be called before a renderer has been set. - */ - public void onPause() { - mGLThread.onPause(); - } - - /** - * Inform the view that the activity is resumed. The owner of this view must - * call this method when the activity is resumed. Calling this method will - * recreate the OpenGL display and resume the rendering - * thread. - * Must not be called before a renderer has been set. - */ - public void onResume() { - mGLThread.onResume(); - } - - /** - * Queue a runnable to be run on the GL rendering thread. This can be used - * to communicate with the Renderer on the rendering thread. - * Must not be called before a renderer has been set. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - mGLThread.queueEvent(r); - } - - /** - * This method is used as part of the View class and is not normally - * called or subclassed by clients of GLSurfaceView. - * Must not be called before a renderer has been set. - */ - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - mGLThread.requestExitAndWait(); - } - - // ---------------------------------------------------------------------- - - /** - * An interface used to wrap a GL interface. - *

Typically - * used for implementing debugging and tracing on top of the default - * GL interface. You would typically use this by creating your own class - * that implemented all the GL methods by delegating to another GL instance. - * Then you could add your own behavior before or after calling the - * delegate. All the GLWrapper would do was instantiate and return the - * wrapper GL instance: - *

-     * class MyGLWrapper implements GLWrapper {
-     *     GL wrap(GL gl) {
-     *         return new MyGLImplementation(gl);
-     *     }
-     *     static class MyGLImplementation implements GL,GL10,GL11,... {
-     *         ...
-     *     }
-     * }
-     * 
- * @see #setGLWrapper(GLWrapper) - */ - public interface GLWrapper { - /** - * Wraps a gl interface in another gl interface. - * @param gl a GL interface that is to be wrapped. - * @return either the input argument or another GL object that wraps the input argument. - */ - GL wrap(GL gl); - } - - /** - * A generic renderer interface. - *

- * The renderer is responsible for making OpenGL calls to render a frame. - *

- * GLSurfaceView clients typically create their own classes that implement - * this interface, and then call {@link GLSurfaceView#setRenderer} to - * register the renderer with the GLSurfaceView. - *

- *

Threading

- * The renderer will be called on a separate thread, so that rendering - * performance is decoupled from the UI thread. Clients typically need to - * communicate with the renderer from the UI thread, because that's where - * input events are received. Clients can communicate using any of the - * standard Java techniques for cross-thread communication, or they can - * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. - *

- *

EGL Context Lost

- * There are situations where the EGL rendering context will be lost. This - * typically happens when device wakes up after going to sleep. When - * the EGL context is lost, all OpenGL resources (such as textures) that are - * associated with that context will be automatically deleted. In order to - * keep rendering correctly, a renderer must recreate any lost resources - * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method - * is a convenient place to do this. - * - * - * @see #setRenderer(Renderer) - */ - public static interface SwapBuffersCallback { - public boolean SwapBuffers(); - } - - public static abstract class Renderer { - /** - * Called when the surface is created or recreated. - *

- * Called when the rendering thread - * starts and whenever the EGL context is lost. The context will typically - * be lost when the Android device awakes after going to sleep. - *

- * Since this method is called at the beginning of rendering, as well as - * every time the EGL context is lost, this method is a convenient place to put - * code to create resources that need to be created when the rendering - * starts, and that need to be recreated when the EGL context is lost. - * Textures are an example of a resource that you might want to create - * here. - *

- * Note that when the EGL context is lost, all OpenGL resources associated - * with that context will be automatically deleted. You do not need to call - * the corresponding "glDelete" methods such as glDeleteTextures to - * manually delete these lost resources. - *

- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param config the EGLConfig of the created surface. Can be used - * to create matching pbuffers. - */ - public abstract void onSurfaceCreated(GL10 gl, EGLConfig config); - - /** - * Called when the surface changed size. - *

- * Called after the surface is created and whenever - * the OpenGL ES surface size changes. - *

- * Typically you will set your viewport here. If your camera - * is fixed then you could also set your projection matrix here: - *

-         * void onSurfaceChanged(GL10 gl, int width, int height) {
-         *     gl.glViewport(0, 0, width, height);
-         *     // for a fixed camera, set the projection too
-         *     float ratio = (float) width / height;
-         *     gl.glMatrixMode(GL10.GL_PROJECTION);
-         *     gl.glLoadIdentity();
-         *     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
-         * }
-         * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param width - * @param height - */ - public abstract void onSurfaceChanged(GL10 gl, int width, int height); - - /** - * Called to draw the current frame. - *

- * This method is responsible for drawing the current frame. - *

- * The implementation of this method typically looks like this: - *

-         * void onDrawFrame(GL10 gl) {
-         *     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
-         *     //... other gl calls to render the scene ...
-         * }
-         * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - */ - public abstract void onDrawFrame(GL10 gl); - - public boolean SwapBuffers() { - if( mSwapBuffersCallback != null ) - return mSwapBuffersCallback.SwapBuffers(); - return false; - } - - public void setSwapBuffersCallback( SwapBuffersCallback c ) { - mSwapBuffersCallback = c; - } - - private SwapBuffersCallback mSwapBuffersCallback = null; - } - - /** - * An interface for customizing the eglCreateContext and eglDestroyContext calls. - *

- * This interface must be implemented by clients wishing to call - * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)} - */ - public interface EGLContextFactory { - EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); - void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); - } - - private static class DefaultContextFactory implements EGLContextFactory { - - public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { - return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null); - } - - public void destroyContext(EGL10 egl, EGLDisplay display, - EGLContext context) { - egl.eglDestroyContext(display, context); - } - } - - /** - * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. - *

- * This interface must be implemented by clients wishing to call - * {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} - */ - public interface EGLWindowSurfaceFactory { - EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, - Object nativeWindow); - void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); - } - - private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { - - public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, - EGLConfig config, Object nativeWindow) { - return egl.eglCreateWindowSurface(display, config, nativeWindow, null); - } - - public void destroySurface(EGL10 egl, EGLDisplay display, - EGLSurface surface) { - egl.eglDestroySurface(display, surface); - } - } - - /** - * An interface for choosing an EGLConfig configuration from a list of - * potential configurations. - *

- * This interface must be implemented by clients wishing to call - * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} - */ - public interface EGLConfigChooser { - /** - * Choose a configuration from the list. Implementors typically - * implement this method by calling - * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the - * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. - * @param egl the EGL10 for the current display. - * @param display the current display. - * @return the chosen configuration. - */ - EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); - } - - private static abstract class BaseConfigChooser - implements EGLConfigChooser { - public BaseConfigChooser(int[] configSpec) { - mConfigSpec = configSpec; - } - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - int[] num_config = new int[1]; - egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config); - - int numConfigs = num_config[0]; - - if (numConfigs <= 0) { - throw new IllegalArgumentException( - "No configs match configSpec"); - } - - EGLConfig[] configs = new EGLConfig[numConfigs]; - egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, - num_config); - EGLConfig config = chooseConfig(egl, display, configs); - if (config == null) { - throw new IllegalArgumentException("No config chosen"); - } - return config; - } - - abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs); - - protected int[] mConfigSpec; - } - - private static class ComponentSizeChooser extends BaseConfigChooser { - public ComponentSizeChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - super(new int[] { - EGL10.EGL_RED_SIZE, redSize, - EGL10.EGL_GREEN_SIZE, greenSize, - EGL10.EGL_BLUE_SIZE, blueSize, - EGL10.EGL_ALPHA_SIZE, alphaSize, - EGL10.EGL_DEPTH_SIZE, depthSize, - EGL10.EGL_STENCIL_SIZE, stencilSize, - EGL10.EGL_NONE}); - mValue = new int[1]; - mRedSize = redSize; - mGreenSize = greenSize; - mBlueSize = blueSize; - mAlphaSize = alphaSize; - mDepthSize = depthSize; - mStencilSize = stencilSize; - } - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs) { - EGLConfig closestConfig = null; - int closestDistance = 1000; - 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); - if (d >= mDepthSize && s>= mStencilSize) { - 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); - int distance = Math.abs(r - mRedSize) - + Math.abs(g - mGreenSize) - + Math.abs(b - mBlueSize) - + Math.abs(a - mAlphaSize); - if (distance < closestDistance) { - closestDistance = distance; - closestConfig = config; - } - } - } - return closestConfig; - } - - 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 int[] mValue; - // Subclasses can adjust these values: - protected int mRedSize; - protected int mGreenSize; - protected int mBlueSize; - protected int mAlphaSize; - protected int mDepthSize; - protected int mStencilSize; - } - - /** - * This class will choose a supported surface as close to - * RGB565 as possible, with or without a depth buffer. - * - */ - private static class SimpleEGLConfigChooser extends ComponentSizeChooser { - public SimpleEGLConfigChooser(boolean withDepthBuffer) { - super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0); - // Adjust target values. This way we'll accept a 4444 or - // 555 buffer if there's no 565 buffer available. - mRedSize = 5; - mGreenSize = 6; - mBlueSize = 5; - } - } - - /** - * An EGL helper class. - */ - - private class EglHelper { - public EglHelper() { - - } - - /** - * Initialize EGL for a given configuration spec. - * @param configSpec - */ - public void start(){ - /* - * Get an EGL instance - */ - mEgl = (EGL10) EGLContext.getEGL(); - - /* - * Get to the default display. - */ - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - /* - * We can now initialize EGL for that display - */ - int[] version = new int[2]; - mEgl.eglInitialize(mEglDisplay, version); - mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); - - /* - * Create an OpenGL ES context. This must be done only once, an - * OpenGL context is a somewhat heavy object. - */ - mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); - if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { - throw new RuntimeException("createContext failed"); - } - - mEglSurface = null; - } - - /* - * React to the creation of a new surface by creating and returning an - * OpenGL interface that renders to that surface. - */ - public GL createSurface(SurfaceHolder holder) { - /* - * The window size has changed, so we need to create a new - * surface. - */ - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { - - /* - * Unbind and destroy the old EGL surface, if - * there is one. - */ - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); - } - - /* - * Create an EGL surface we can render into. - */ - mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, - mEglDisplay, mEglConfig, holder); - - if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { - throwEglException("createWindowSurface"); - } - - /* - * Before we can issue GL commands, we need to make sure - * the context is current and bound to a surface. - */ - if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { - throwEglException("eglMakeCurrent"); - } - - GL gl = mEglContext.getGL(); - if (mGLWrapper != null) { - gl = mGLWrapper.wrap(gl); - } - - return gl; - } - - /** - * Display the current render surface. - * @return false if the context has been lost. - */ - public boolean swap() { - mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); - - /* - * Always check for EGL_CONTEXT_LOST, which means the context - * and all associated data were lost (For instance because - * the device went to sleep). We need to sleep until we - * get a new surface. - */ - return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST; - } - - public void destroySurface() { - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_CONTEXT); - mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); - mEglSurface = null; - } - } - - public void finish() { - if (mEglContext != null) { - mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); - mEglContext = null; - } - if (mEglDisplay != null) { - mEgl.eglTerminate(mEglDisplay); - mEglDisplay = null; - } - } - - private void throwEglException(String function) { - throw new RuntimeException(function + " failed: " + mEgl.eglGetError()); - } - - EGL10 mEgl; - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLConfig mEglConfig; - EGLContext mEglContext; - } - - /** - * A generic GL Thread. Takes care of initializing EGL and GL. Delegates - * to a Renderer instance to do the actual drawing. Can be configured to - * render continuously or on request. - * - * All potentially blocking synchronization is done through the - * sGLThreadManager object. This avoids multiple-lock ordering issues. - * - */ - class GLThread extends Thread implements SwapBuffersCallback { - GLThread(Renderer renderer) { - super(); - mWidth = 0; - mHeight = 0; - mRequestRender = true; - mRenderMode = RENDERMODE_CONTINUOUSLY; - mRenderer = renderer; - mRenderer.setSwapBuffersCallback(this); - } - - @Override - public void run() { - setName("GLThread " + getId()); - if (LOG_THREADS) { - Log.i("GLThread", "starting tid=" + getId()); - } - - mEglHelper = new EglHelper(); - SwapBuffers(); - SwapBuffers(); - - mRenderer.onDrawFrame(mGL); - - synchronized (sGLThreadManager) { - stopEglLocked(); - } - - sGLThreadManager.threadExiting(this); - } - - /* - * This private method should only be called inside a - * synchronized(sGLThreadManager) block. - */ - private void stopEglLocked() { - if (mHaveEgl) { - mHaveEgl = false; - mEglHelper.destroySurface(); - mEglHelper.finish(); - sGLThreadManager.releaseEglSurfaceLocked(this); - } - } - - public boolean SwapBuffers() { - try { - - boolean createEglSurface = false; - boolean sizeChanged = false; - int w = 0; - int h = 0; - Runnable event = null; - - synchronized (sGLThreadManager) { - while (true) { - if (mShouldExit) { - return false; - } - - if (! mEventQueue.isEmpty()) { - event = mEventQueue.remove(0); - break; - } - - // Do we need to release the EGL surface? - if (mHaveEgl && mPaused) { - if (LOG_SURFACE) { - Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); - } - stopEglLocked(); - } - - // Have we lost the surface view surface? - if ((! mHasSurface) && (! mWaitingForSurface)) { - if (LOG_SURFACE) { - Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); - } - if (mHaveEgl) { - stopEglLocked(); - } - mWaitingForSurface = true; - sGLThreadManager.notifyAll(); - } - - // Have we acquired the surface view surface? - if (mHasSurface && mWaitingForSurface) { - if (LOG_SURFACE) { - Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); - } - mWaitingForSurface = false; - sGLThreadManager.notifyAll(); - } - - // Ready to draw? - if ((!mPaused) && mHasSurface - && (mWidth > 0) && (mHeight > 0) - && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { - - // If we don't have an egl surface, try to acquire one. - if ((! mHaveEgl) && sGLThreadManager.tryAcquireEglSurfaceLocked(this)) { - mHaveEgl = true; - mEglHelper.start(); - createEglSurface = true; - sizeChanged = true; - sGLThreadManager.notifyAll(); - } - - if (mHaveEgl) { - if (mSizeChanged) { - sizeChanged = true; - w = mWidth; - h = mHeight; - if (DRAW_TWICE_AFTER_SIZE_CHANGED) { - // We keep mRequestRender true so that we draw twice after the size changes. - // (Once because of mSizeChanged, the second time because of mRequestRender.) - // This forces the updated graphics onto the screen. - } else { - mRequestRender = false; - } - mSizeChanged = false; - } else { - mRequestRender = false; - } - sGLThreadManager.notifyAll(); - break; - } - } - - // By design, this is the only place in a GLThread thread where we wait(). - if (LOG_THREADS) { - Log.i("GLThread", "waiting tid=" + getId()); - } - sGLThreadManager.wait(); - } - } // end of synchronized(sGLThreadManager) - - if (event != null) { - event.run(); - event = null; - } - - if (createEglSurface) { - mGL = (GL10) mEglHelper.createSurface(getHolder()); - if (LOG_RENDERER) { - Log.w("GLThread", "onSurfaceCreated"); - } - mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig); - createEglSurface = false; - } - - if (sizeChanged) { - if (LOG_RENDERER) { - Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); - } - mRenderer.onSurfaceChanged(mGL, w, h); - sizeChanged = false; - } - - if (LOG_RENDERER) { - Log.w("GLThread", "onDrawFrame"); - } - if(!mEglHelper.swap()) { - if (LOG_SURFACE) { - Log.i("GLThread", "egl surface lost tid=" + getId()); - return false; - } - } - - } catch (InterruptedException e) { - return false; - } - return true; - } - - public void setRenderMode(int renderMode) { - if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { - throw new IllegalArgumentException("renderMode"); - } - synchronized(sGLThreadManager) { - mRenderMode = renderMode; - sGLThreadManager.notifyAll(); - } - } - - public int getRenderMode() { - synchronized(sGLThreadManager) { - return mRenderMode; - } - } - - public void requestRender() { - synchronized(sGLThreadManager) { - mRequestRender = true; - sGLThreadManager.notifyAll(); - } - } - - public void surfaceCreated() { - synchronized(sGLThreadManager) { - if (LOG_THREADS) { - Log.i("GLThread", "surfaceCreated tid=" + getId()); - } - mHasSurface = true; - sGLThreadManager.notifyAll(); - } - } - - public void surfaceDestroyed() { - synchronized(sGLThreadManager) { - if (LOG_THREADS) { - Log.i("GLThread", "surfaceDestroyed tid=" + getId()); - } - mHasSurface = false; - sGLThreadManager.notifyAll(); - while((!mWaitingForSurface) && (!mExited)) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void onPause() { - synchronized (sGLThreadManager) { - mPaused = true; - sGLThreadManager.notifyAll(); - } - } - - public void onResume() { - synchronized (sGLThreadManager) { - mPaused = false; - mRequestRender = true; - sGLThreadManager.notifyAll(); - } - } - - public void onWindowResize(int w, int h) { - synchronized (sGLThreadManager) { - mWidth = w; - mHeight = h; - mSizeChanged = true; - mRequestRender = true; - sGLThreadManager.notifyAll(); - } - } - - public void requestExitAndWait() { - // don't call this from GLThread thread or it is a guaranteed - // deadlock! - synchronized(sGLThreadManager) { - mShouldExit = true; - sGLThreadManager.notifyAll(); - while (! mExited) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - /** - * Queue an "event" to be run on the GL rendering thread. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - if (r == null) { - throw new IllegalArgumentException("r must not be null"); - } - synchronized(sGLThreadManager) { - mEventQueue.add(r); - sGLThreadManager.notifyAll(); - } - } - - // Once the thread is started, all accesses to the following member - // variables are protected by the sGLThreadManager monitor - private boolean mShouldExit; - private boolean mExited; - private boolean mPaused; - private boolean mHasSurface; - private boolean mWaitingForSurface; - private boolean mHaveEgl; - private int mWidth; - private int mHeight; - private int mRenderMode; - private boolean mRequestRender; - private ArrayList mEventQueue = new ArrayList(); - // End of member variables protected by the sGLThreadManager monitor. - - private Renderer mRenderer; - private EglHelper mEglHelper; - private GL10 mGL = null; - } - - static class LogWriter extends Writer { - - @Override public void close() { - flushBuilder(); - } - - @Override public void flush() { - flushBuilder(); - } - - @Override public void write(char[] buf, int offset, int count) { - for(int i = 0; i < count; i++) { - char c = buf[offset + i]; - if ( c == '\n') { - flushBuilder(); - } - else { - mBuilder.append(c); - } - } - } - - private void flushBuilder() { - if (mBuilder.length() > 0) { - Log.v("GLSurfaceView", mBuilder.toString()); - mBuilder.delete(0, mBuilder.length()); - } - } - - private StringBuilder mBuilder = new StringBuilder(); - } - - - private void checkRenderThreadState() { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - } - - private static class GLThreadManager { - - public synchronized void threadExiting(GLThread thread) { - if (LOG_THREADS) { - Log.i("GLThread", "exiting tid=" + thread.getId()); - } - thread.mExited = true; - if (mEglOwner == thread) { - mEglOwner = null; - } - notifyAll(); - } - - /* - * Tries once to acquire the right to use an EGL - * surface. Does not block. Requires that we are already - * in the sGLThreadManager monitor when this is called. - * @return true if the right to use an EGL surface was acquired. - */ - public boolean tryAcquireEglSurfaceLocked(GLThread thread) { - if (mEglOwner == thread || mEglOwner == null) { - mEglOwner = thread; - notifyAll(); - return true; - } - return false; - } - /* - * Releases the EGL surface. Requires that we are already in the - * sGLThreadManager monitor when this is called. - */ - public void releaseEglSurfaceLocked(GLThread thread) { - if (mEglOwner == thread) { - mEglOwner = null; - } - notifyAll(); - } - - private GLThread mEglOwner; - } - - private static final GLThreadManager sGLThreadManager = new GLThreadManager(); - private boolean mSizeChanged = true; - - private GLThread mGLThread; - private EGLConfigChooser mEGLConfigChooser; - private EGLContextFactory mEGLContextFactory; - private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; - private GLWrapper mGLWrapper; - private int mDebugFlags; -}