Android OpenGL ES 相关的包主要定义在
- javax.microedition.khronos.opengles GL 绘图指令
- javax.microedition.khronos.egl EGL 管理Display, surface等
- android.opengl Android GL辅助类,连接OpenGL 与Android View,Activity
- javax.nio Buffer类
其中GLSurfaceView 为android.opengl 包中核心类:
- 起到连接OpenGL ES与Android 的View层次结构之间的桥梁作用。
- 使得Open GL ES库适应于Anndroid系统的Activity生命周期。
- 使得选择合适的Frame buffer像素格式变得容易。
- 创建和管理单独绘图线程以达到平滑动画效果。
- 提供了方便使用的调试工具来跟踪OpenGL ES函数调用以帮助检查错误。
使用过Java ME ,JSR 239 开发过OpenGL ES可以看到 Android 包javax.microedition.khronos.egl ,javax.microedition.khronos.opengles 和JSR239 基本一致,因此理论上不使用android.opengl 包中的类也可以开发Android上OpenGL ES应用,但此时就需要自己使用EGL来管理Display,Context, Surfaces 的创建,释放,捆绑。
使用EGL 实现GLSurfaceView一个可能的实现如下:
- class GLSurfaceView extends SurfaceView
- implements SurfaceHolder.Callback, Runnable {
- public GLSurfaceView(Context context) {
- super(context);
- mHolder = getHolder();
- mHolder.addCallback(this);
- mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
- }
-
- public void setRenderer(Renderer renderer) {
- mRenderer = renderer;
- }
-
- public void surfaceCreated(SurfaceHolder holder) {
- }
-
- public void surfaceDestroyed(SurfaceHolder holder) {
- running = false;
- try {
- thread.join();
- } catch (InterruptedException e) {
- }
- thread = null;
- }
-
- public void surfaceChanged(SurfaceHolder holder,
- int format, int w, int h) {
- synchronized(this){
- mWidth = w;
- mHeight = h;
- thread = new Thread(this);
- thread.start();
- }
- }
-
- public interface Renderer {
- void EGLCreate(SurfaceHolder holder);
- void EGLDestroy();
- int Initialize(int width, int height);
- void DrawScene(int width, int height);
- }
-
- public void run() {
- synchronized(this) {
- mRenderer.EGLCreate(mHolder);
- mRenderer.Initialize(mWidth, mHeight);
-
- running=true;
- while (running) {
- mRenderer.DrawScene(mWidth, mHeight);
- }
-
- mRenderer.EGLDestroy();
- }
- }
-
- private SurfaceHolder mHolder;
- private Thread thread;
- private boolean running;
- private Renderer mRenderer;
- private int mWidth;
- private int mHeight;
-
- }
-
- class GLRenderer implements GLSurfaceView.Renderer {
- public GLRenderer() {
- }
-
- public int Initialize(int width, int height){
- gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
-
- return 1;
- }
-
- public void DrawScene(int width, int height){
- gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
-
- egl.eglSwapBuffers(eglDisplay, eglSurface);
- }
-
- public void EGLCreate(SurfaceHolder holder){
- int[] num_config = new int[1];
- EGLConfig[] configs = new EGLConfig[1];
- int[] configSpec = {
- EGL10.EGL_RED_SIZE, 8,
- EGL10.EGL_GREEN_SIZE, 8,
- EGL10.EGL_BLUE_SIZE, 8,
-
- EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
- EGL10.EGL_NONE
- };
-
- this.egl = (EGL10) EGLContext.getEGL();
-
- eglDisplay = this.egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
- this.egl.eglInitialize(eglDisplay, null);
-
- this.egl.eglChooseConfig(eglDisplay, configSpec,
- configs, 1, num_config);
-
- eglConfig = configs[0];
- eglContext = this.egl.eglCreateContext(eglDisplay, eglConfig,
- EGL10.EGL_NO_CONTEXT, null);
-
- eglSurface = this.egl.eglCreateWindowSurface(eglDisplay,
- eglConfig, holder, null);
-
- this.egl.eglMakeCurrent(eglDisplay, eglSurface,
- eglSurface, eglContext);
-
- gl = (GL10)eglContext.getGL();
- }
-
- public void EGLDestroy(){
- if (eglSurface != null) {
- egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- egl.eglDestroySurface(eglDisplay, eglSurface);
- eglSurface = null;
- }
- if (eglContext != null) {
- egl.eglDestroyContext(eglDisplay, eglContext);
- eglContext = null;
- }
- if (eglDisplay != null) {
- egl.eglTerminate(eglDisplay);
- eglDisplay = null;
- }
- }
-
- private EGL10 egl;
- private GL10 gl;
- private EGLDisplay eglDisplay;
- private EGLConfig eglConfig;
- private EGLContext eglContext;
- private EGLSurface eglSurface;
- }
可以看到需要派生SurfaceView ,并手工创建,销毁Display,Context ,工作繁琐。
使用GLSurfaceView 内部提供了上面类似的实现,对于大部分应用只需调用一个方法来设置OpenGLView用到的GLSurfaceView.Renderer.
- public void setRenderer(GLSurfaceView.Renderer renderer)
GLSurfaceView.Renderer定义了一个统一图形绘制的接口,它定义了如下三个接口函数:
-
- public void onSurfaceCreated(GL10 gl, EGLConfig config)
-
- public void onDrawFrame(GL10 gl)
-
- public void onSurfaceChanged(GL10 gl, int width, int height)
- onSurfaceCreated : 在这个方法中主要用来设置一些绘制时不常变化的参数,比如:背景色,是否打开 z-buffer等。
- onDrawFrame: 定义实际的绘图操作。
- onSurfaceChanged: 如果设备支持屏幕横向和纵向切换,这个方法将发生在横向<->纵向互换时。此时可以重新设置绘制的纵横比率。
如果有需要,也可以通过函数来修改GLSurfaceView一些缺省设置:
- setDebugFlags(int) 设置Debug标志。
- setEGLConfigChooser (boolean) 选择一个Config接近16bitRGB颜色模式,可以打开或关闭深度(Depth)Buffer ,缺省为RGB_565 并打开至少有16bit 的 depth Buffer.
- setEGLConfigChooser(EGLConfigChooser) 选择自定义EGLConfigChooser。
- setEGLConfigChooser(int, int, int, int, int, int) 指定red ,green, blue, alpha, depth ,stencil 支持的位数,缺省为RGB_565 ,16 bit depth buffer.
GLSurfaceView 缺省创建为RGB_565 颜色格式的Surface ,如果需要支持透明度,可以调用getHolder().setFormat(PixelFormat.TRANSLUCENT).
GLSurfaceView 的渲染模式有两种,一种是连续不断的更新屏幕,另一种为on-demand ,只有在调用requestRender() 在更新屏幕。 缺省为RENDERMODE_CONTINUOUSLY 持续刷新屏幕。
GLSurfaceView是我认为Android源码体系中一个非常值得研究和学习的源代码,当你完全看懂GLSurfaceView的大部分代码和代码结构设计对你在以后的编码过程中设计自己的功能模块时有很好的借鉴作用。
如下代码是完全按照系统的GLSurfaceView的代码结构设计的动态GL壁纸Engine,能够非常方便的实现OpenGL方式的动态壁纸:
- public class GLWallpaperService extends WallpaperService {
- private static final String TAG = "GLWallpaperService";
-
- @Override
- public Engine onCreateEngine() {
- return new GLEngine();
- }
-
- public class GLEngine extends Engine {
- public final static int RENDERMODE_WHEN_DIRTY = 0;
- public final static int RENDERMODE_CONTINUOUSLY = 1;
-
- private GLThread mGLThread;
- private EGLConfigChooser mEGLConfigChooser;
- private EGLContextFactory mEGLContextFactory;
- private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
- private GLWrapper mGLWrapper;
- private int mDebugFlags;
-
- public GLEngine() {
- super();
- }
-
- @Override
- public void onVisibilityChanged(boolean visible) {
- if (visible) {
- onResume();
- } else {
- onPause();
- }
- super.onVisibilityChanged(visible);
- }
-
- @Override
- public void onCreate(SurfaceHolder surfaceHolder) {
- super.onCreate(surfaceHolder);
-
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
-
- mGLThread.requestExitAndWait();
- }
-
- @Override
- public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-
- mGLThread.onWindowResize(width, height);
- super.onSurfaceChanged(holder, format, width, height);
- }
-
- @Override
- public void onSurfaceCreated(SurfaceHolder holder) {
- Log.d(TAG, "onSurfaceCreated()");
- mGLThread.surfaceCreated(holder);
- super.onSurfaceCreated(holder);
- }
-
- @Override
- public void onSurfaceDestroyed(SurfaceHolder holder) {
- Log.d(TAG, "onSurfaceDestroyed()");
- mGLThread.surfaceDestroyed();
- super.onSurfaceDestroyed(holder);
- }
-
-
-
-
- public void setGLWrapper(GLWrapper glWrapper) {
- mGLWrapper = glWrapper;
- }
-
- public void setDebugFlags(int debugFlags) {
- mDebugFlags = debugFlags;
- }
-
- public int getDebugFlags() {
- return mDebugFlags;
- }
-
- 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, mEGLConfigChooser, mEGLContextFactory, mEGLWindowSurfaceFactory, mGLWrapper);
- mGLThread.start();
- }
-
- public void setEGLContextFactory(EGLContextFactory factory) {
- checkRenderThreadState();
- mEGLContextFactory = factory;
- }
-
- public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {
- checkRenderThreadState();
- mEGLWindowSurfaceFactory = factory;
- }
-
- public void setEGLConfigChooser(EGLConfigChooser configChooser) {
- checkRenderThreadState();
- mEGLConfigChooser = configChooser;
- }
-
- public void setEGLConfigChooser(boolean needDepth) {
- setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));
- }
-
- public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, int alphaSize, int depthSize,
- int stencilSize) {
- setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, blueSize, alphaSize, depthSize,
- stencilSize));
- }
-
- public void setRenderMode(int renderMode) {
- mGLThread.setRenderMode(renderMode);
- }
-
- public int getRenderMode() {
- return mGLThread.getRenderMode();
- }
-
- public void requestRender() {
- mGLThread.requestRender();
- }
-
- public void onPause() {
- mGLThread.onPause();
- }
-
- public void onResume() {
- mGLThread.onResume();
- }
-
- public void queueEvent(Runnable r) {
- mGLThread.queueEvent(r);
- }
-
- private void checkRenderThreadState() {
- if (mGLThread != null) {
- throw new IllegalStateException("setRenderer has already been called for this instance.");
- }
- }
- }
-
- public interface Renderer {
-
- public void onSurfaceCreated(GL10 gl, EGLConfig config);
-
- public void onSurfaceChanged(GL10 gl, int width, int height);
-
- public void onDrawFrame(GL10 gl);
- }
- }
-
- class LogWriter extends Writer {
- private StringBuilder mBuilder = new StringBuilder();
-
- @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());
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
- interface EGLContextFactory {
- EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig);
-
- void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
- }
-
- 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);
- }
- }
-
-
-
-
-
-
-
-
- interface EGLWindowSurfaceFactory {
- EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, Object nativeWindow);
-
- void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface);
- }
-
- class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
-
- public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay
- display, EGLConfig config, Object nativeWindow) {
-
- EGLSurface eglSurface = null;
- while (eglSurface == null) {
- try {
- eglSurface = egl.eglCreateWindowSurface(display,
- config, nativeWindow, null);
- } catch (Throwable t) {
- } finally {
- if (eglSurface == null) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException t) {
- }
- }
- }
- }
- return eglSurface;
- }
-
- public void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface) {
- egl.eglDestroySurface(display, surface);
- }
- }
-
- interface GLWrapper {
-
-
-
-
-
-
-
- GL wrap(GL gl);
- }
-
- class EglHelper {
-
- private EGL10 mEgl;
- private EGLDisplay mEglDisplay;
- private EGLSurface mEglSurface;
- private EGLContext mEglContext;
- EGLConfig mEglConfig;
-
- private EGLConfigChooser mEGLConfigChooser;
- private EGLContextFactory mEGLContextFactory;
- private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
- private GLWrapper mGLWrapper;
-
- public EglHelper(EGLConfigChooser chooser, EGLContextFactory contextFactory,
- EGLWindowSurfaceFactory surfaceFactory, GLWrapper wrapper) {
- this.mEGLConfigChooser = chooser;
- this.mEGLContextFactory = contextFactory;
- this.mEGLWindowSurfaceFactory = surfaceFactory;
- this.mGLWrapper = wrapper;
- }
-
-
-
-
-
-
- public void start() {
-
- if (mEgl == null) {
-
-
-
-
- mEgl = (EGL10) EGLContext.getEGL();
- } else {
-
- }
-
- if (mEglDisplay == null) {
-
-
-
-
- mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
- } else {
-
- }
-
- if (mEglConfig == null) {
-
-
-
-
- int[] version = new int[2];
- mEgl.eglInitialize(mEglDisplay, version);
- mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
- } else {
-
- }
-
- if (mEglContext == null) {
-
-
-
-
- mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
- if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
- throw new RuntimeException("createContext failed");
- }
- } else {
-
- }
-
- mEglSurface = null;
- }
-
-
-
-
-
- public GL createSurface(SurfaceHolder holder) {
-
-
-
- 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 = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, holder);
-
- if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
- throw new RuntimeException("createWindowSurface failed");
- }
-
-
-
-
- if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- throw new RuntimeException("eglMakeCurrent failed.");
- }
-
- GL gl = mEglContext.getGL();
- if (mGLWrapper != null) {
- gl = mGLWrapper.wrap(gl);
- }
-
-
-
-
-
-
-
- return gl;
- }
-
-
-
-
-
-
- public boolean swap() {
- mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
-
-
-
-
-
- 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;
- }
- }
- }
-
- class GLThread extends Thread {
- private final static boolean LOG_THREADS = false;
- public final static int DEBUG_CHECK_GL_ERROR = 1;
- public final static int DEBUG_LOG_GL_CALLS = 2;
-
- private final GLThreadManager sGLThreadManager = new GLThreadManager();
- private GLThread mEglOwner;
-
- private EGLConfigChooser mEGLConfigChooser;
- private EGLContextFactory mEGLContextFactory;
- private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
- private GLWrapper mGLWrapper;
-
- public SurfaceHolder mHolder;
- private boolean mSizeChanged = true;
-
-
-
- public boolean mDone;
- 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 boolean mEventsWaiting;
-
-
- private GLWallpaperService.Renderer mRenderer;
- private ArrayList mEventQueue = new ArrayList();
- private EglHelper mEglHelper;
-
- GLThread(GLWallpaperService.Renderer renderer, EGLConfigChooser chooser, EGLContextFactory contextFactory,
- EGLWindowSurfaceFactory surfaceFactory, GLWrapper wrapper) {
- super();
- mDone = false;
- mWidth = 0;
- mHeight = 0;
- mRequestRender = true;
- mRenderMode = GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY;
- mRenderer = renderer;
- this.mEGLConfigChooser = chooser;
- this.mEGLContextFactory = contextFactory;
- this.mEGLWindowSurfaceFactory = surfaceFactory;
- this.mGLWrapper = wrapper;
- }
-
- @Override
- public void run() {
- setName("GLThread " + getId());
- if (LOG_THREADS) {
- Log.i("GLThread", "starting tid=" + getId());
- }
-
- try {
- guardedRun();
- } catch (InterruptedException e) {
-
- } finally {
- sGLThreadManager.threadExiting(this);
- }
- }
-
-
-
-
- private void stopEglLocked() {
- if (mHaveEgl) {
- mHaveEgl = false;
- mEglHelper.destroySurface();
- sGLThreadManager.releaseEglSurface(this);
- }
- }
-
- private void guardedRun() throws InterruptedException {
- mEglHelper = new EglHelper(mEGLConfigChooser, mEGLContextFactory, mEGLWindowSurfaceFactory, mGLWrapper);
- try {
- GL10 gl = null;
- boolean tellRendererSurfaceCreated = true;
- boolean tellRendererSurfaceChanged = true;
-
-
-
-
- while (!isDone()) {
-
-
-
- int w = 0;
- int h = 0;
- boolean changed = false;
- boolean needStart = false;
- boolean eventsWaiting = false;
-
- synchronized (sGLThreadManager) {
- while (true) {
-
-
- if (mPaused) {
- stopEglLocked();
- }
- if (!mHasSurface) {
- if (!mWaitingForSurface) {
- stopEglLocked();
- mWaitingForSurface = true;
- sGLThreadManager.notifyAll();
- }
- } else {
- if (!mHaveEgl) {
- if (sGLThreadManager.tryAcquireEglSurface(this)) {
- mHaveEgl = true;
- mEglHelper.start();
- mRequestRender = true;
- needStart = true;
- }
- }
- }
-
-
-
-
-
-
- if (mDone) {
- return;
- }
-
- if (mEventsWaiting) {
- eventsWaiting = true;
- mEventsWaiting = false;
- break;
- }
-
- if ((!mPaused) && mHasSurface && mHaveEgl && (mWidth > 0) && (mHeight > 0)
- && (mRequestRender || (mRenderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) {
- changed = mSizeChanged;
- w = mWidth;
- h = mHeight;
- mSizeChanged = false;
- mRequestRender = false;
- if (mHasSurface && mWaitingForSurface) {
- changed = true;
- mWaitingForSurface = false;
- sGLThreadManager.notifyAll();
- }
- break;
- }
-
-
-
- if (LOG_THREADS) {
- Log.i("GLThread", "waiting tid=" + getId());
- }
- sGLThreadManager.wait();
- }
- }
-
-
-
-
- if (eventsWaiting) {
- Runnable r;
- while ((r = getEvent()) != null) {
- r.run();
- if (isDone()) {
- return;
- }
- }
-
- continue;
- }
-
- if (needStart) {
- tellRendererSurfaceCreated = true;
- changed = true;
- }
- if (changed) {
- gl = (GL10) mEglHelper.createSurface(mHolder);
- tellRendererSurfaceChanged = true;
- }
- if (tellRendererSurfaceCreated) {
- mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
- tellRendererSurfaceCreated = false;
- }
- if (tellRendererSurfaceChanged) {
- mRenderer.onSurfaceChanged(gl, w, h);
- tellRendererSurfaceChanged = false;
- }
- if ((w > 0) && (h > 0)) {
-
- mRenderer.onDrawFrame(gl);
-
-
-
-
-
- mEglHelper.swap();
- Thread.sleep(10);
- }
- }
- } finally {
-
-
-
- synchronized (sGLThreadManager) {
- stopEglLocked();
- mEglHelper.finish();
- }
- }
- }
-
- private boolean isDone() {
- synchronized (sGLThreadManager) {
- return mDone;
- }
- }
-
- public void setRenderMode(int renderMode) {
- if (!((GLWallpaperService.GLEngine.RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) {
- throw new IllegalArgumentException("renderMode");
- }
- synchronized (sGLThreadManager) {
- mRenderMode = renderMode;
- if (renderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY) {
- sGLThreadManager.notifyAll();
- }
- }
- }
-
- public int getRenderMode() {
- synchronized (sGLThreadManager) {
- return mRenderMode;
- }
- }
-
- public void requestRender() {
- synchronized (sGLThreadManager) {
- mRequestRender = true;
- sGLThreadManager.notifyAll();
- }
- }
-
- public void surfaceCreated(SurfaceHolder holder) {
- mHolder = holder;
- 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 && isAlive() && !mDone) {
- 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;
- sGLThreadManager.notifyAll();
- }
- }
-
- public void requestExitAndWait() {
-
-
- synchronized (sGLThreadManager) {
- mDone = true;
- sGLThreadManager.notifyAll();
- }
- try {
- join();
- } catch (InterruptedException ex) {
- Thread.currentThread().interrupt();
- }
- }
-
-
-
-
-
-
-
- public void queueEvent(Runnable r) {
- synchronized (this) {
- mEventQueue.add(r);
- synchronized (sGLThreadManager) {
- mEventsWaiting = true;
- sGLThreadManager.notifyAll();
- }
- }
- }
-
- private Runnable getEvent() {
- synchronized (this) {
- if (mEventQueue.size() > 0) {
- return mEventQueue.remove(0);
- }
-
- }
- return null;
- }
-
- private class GLThreadManager {
-
- public synchronized void threadExiting(GLThread thread) {
- if (LOG_THREADS) {
- Log.i("GLThread", "exiting tid=" + thread.getId());
- }
- thread.mDone = true;
- if (mEglOwner == thread) {
- mEglOwner = null;
- }
- notifyAll();
- }
-
-
-
-
-
-
- public synchronized boolean tryAcquireEglSurface(GLThread thread) {
- if (mEglOwner == thread || mEglOwner == null) {
- mEglOwner = thread;
- notifyAll();
- return true;
- }
- return false;
- }
-
- public synchronized void releaseEglSurface(GLThread thread) {
- if (mEglOwner == thread) {
- mEglOwner = null;
- }
- notifyAll();
- }
- }
- }
-
- interface EGLConfigChooser {
- EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
- }
-
- 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;
- public 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;
-
- protected int mRedSize;
- protected int mGreenSize;
- protected int mBlueSize;
- protected int mAlphaSize;
- protected int mDepthSize;
- protected int mStencilSize;
- }
-
-
-
-
-
- public static class SimpleEGLConfigChooser extends ComponentSizeChooser {
- public SimpleEGLConfigChooser(boolean withDepthBuffer) {
- super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);
-
-
- mRedSize = 5;
- mGreenSize = 6;
- mBlueSize = 5