package com.stickycoding.rokon;
/*
* Copyright (C) 2010 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.
*/
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.content.pm.ConfigurationInfo;
import android.opengl.GLDebugHelper;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* This is a custom GLSurfaceView taken from Replica Island
* Chris built it because he wanted to switch more reliably between Activities
*/
public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
// 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(Context context) {
super(context);
init();
}
/**
* Standard View constructor. In order to render something, you
* must call {@link #setRenderer} to register a renderer.
*/
public GLSurfaceView(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.
* <p>
* Wrapping is typically used for debugging purposes.
* <p>
* 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.
* <p>This method should be called once and only once in the life-cycle of
* a GLSurfaceView.
* <p>The following GLSurfaceView methods can only be called <em>before</em>
* setRenderer is called:
* <ul>
* <li>{@link #setEGLConfigChooser(boolean)}
* <li>{@link #setEGLConfigChooser(EGLConfigChooser)}
* <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)}
* </ul>
* <p>
* The following GLSurfaceView methods can only be called <em>after</em>
* setRenderer is called:
* <ul>
* <li>{@link #getRenderMode()}
* <li>{@link #onPause()}
* <li>{@link #onResume()}
* <li>{@link #queueEvent(Runnable)}
* <li>{@link #requestRender()}
* <li>{@link #setRenderMode(int)}
* </ul>
*
* @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.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>
* 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.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>
* 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.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>
* 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();
mEG