Android利用OpenGLES开发动态壁纸用到的GLWallpaperService类


Android利用OpenGLES开发动态壁纸用到的GLWallpaperService类:

 
  1. /* 
  2.  * Copyright (C) 2008 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16. import java.io.Writer;  
  17. import java.util.ArrayList;  
  18.   
  19. import javax.microedition.khronos.egl.EGL10;  
  20. import javax.microedition.khronos.egl.EGL11;  
  21. import javax.microedition.khronos.egl.EGLConfig;  
  22. import javax.microedition.khronos.egl.EGLContext;  
  23. import javax.microedition.khronos.egl.EGLDisplay;  
  24. import javax.microedition.khronos.egl.EGLSurface;  
  25. import javax.microedition.khronos.opengles.GL;  
  26. import javax.microedition.khronos.opengles.GL10;  
  27.   
  28. import android.service.wallpaper.WallpaperService;  
  29. import android.util.Log;  
  30. import android.view.SurfaceHolder;  
  31.   
  32. import com.mediawoz.firewallpaper.BaseConfigChooser.ComponentSizeChooser;  
  33. import com.mediawoz.firewallpaper.BaseConfigChooser.SimpleEGLConfigChooser;  
  34.   
  35.   
  36. // Original code provided by Robert Green   
  37. // http://www.rbgrn.net/content/354-glsurfaceview-adapted-3d-live-wallpapers   
  38. public class GLWallpaperService extends WallpaperService {  
  39.     private static final String TAG = "GLWallpaperService";  
  40.   
  41.     @Override  
  42.     public Engine onCreateEngine() {  
  43.         return new GLEngine();  
  44.     }  
  45.   
  46.     public class GLEngine extends Engine {  
  47.         public final static int RENDERMODE_WHEN_DIRTY = 0;  
  48.         public final static int RENDERMODE_CONTINUOUSLY = 1;  
  49.   
  50.         private GLThread mGLThread;  
  51.         private EGLConfigChooser mEGLConfigChooser;  
  52.         private EGLContextFactory mEGLContextFactory;  
  53.         private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;  
  54.         private GLWrapper mGLWrapper;  
  55.         private int mDebugFlags;  
  56.   
  57.         public GLEngine() {  
  58.             super();  
  59.         }  
  60.   
  61.         @Override  
  62.         public void onVisibilityChanged(boolean visible) {  
  63.             if (visible) {  
  64.                 onResume();  
  65.             } else {  
  66.                 onPause();  
  67.             }  
  68.             super.onVisibilityChanged(visible);  
  69.         }  
  70.   
  71.         @Override  
  72.         public void onCreate(SurfaceHolder surfaceHolder) {  
  73.             super.onCreate(surfaceHolder);  
  74.             // Log.d(TAG, "GLEngine.onCreate()");   
  75.         }  
  76.   
  77.         @Override  
  78.         public void onDestroy() {  
  79.             super.onDestroy();  
  80.             // Log.d(TAG, "GLEngine.onDestroy()");   
  81.             mGLThread.requestExitAndWait();  
  82.         }  
  83.   
  84.         @Override  
  85.         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  86.             // Log.d(TAG, "onSurfaceChanged()");   
  87.             mGLThread.onWindowResize(width, height);  
  88.             super.onSurfaceChanged(holder, format, width, height);  
  89.         }  
  90.   
  91.         @Override  
  92.         public void onSurfaceCreated(SurfaceHolder holder) {  
  93.             Log.d(TAG, "onSurfaceCreated()");  
  94.             mGLThread.surfaceCreated(holder);  
  95.             super.onSurfaceCreated(holder);  
  96.         }  
  97.   
  98.         @Override  
  99.         public void onSurfaceDestroyed(SurfaceHolder holder) {  
  100.             Log.d(TAG, "onSurfaceDestroyed()");  
  101.             mGLThread.surfaceDestroyed();  
  102.             super.onSurfaceDestroyed(holder);  
  103.         }  
  104.   
  105.         /** 
  106.          * An EGL helper class. 
  107.          */  
  108.         public void setGLWrapper(GLWrapper glWrapper) {  
  109.             mGLWrapper = glWrapper;  
  110.         }  
  111.   
  112.         public void setDebugFlags(int debugFlags) {  
  113.             mDebugFlags = debugFlags;  
  114.         }  
  115.   
  116.         public int getDebugFlags() {  
  117.             return mDebugFlags;  
  118.         }  
  119.   
  120.         public void setRenderer(Renderer renderer) {  
  121.             checkRenderThreadState();  
  122.             if (mEGLConfigChooser == null) {  
  123.                 mEGLConfigChooser = new SimpleEGLConfigChooser(true);  
  124.             }  
  125.             if (mEGLContextFactory == null) {  
  126.                 mEGLContextFactory = new DefaultContextFactory();  
  127.             }  
  128.             if (mEGLWindowSurfaceFactory == null) {  
  129.                 mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();  
  130.             }  
  131.             mGLThread = new GLThread(renderer, mEGLConfigChooser, mEGLContextFactory, mEGLWindowSurfaceFactory, mGLWrapper);  
  132.             mGLThread.start();  
  133.         }  
  134.   
  135.         public void setEGLContextFactory(EGLContextFactory factory) {  
  136.             checkRenderThreadState();  
  137.             mEGLContextFactory = factory;  
  138.         }  
  139.   
  140.         public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {  
  141.             checkRenderThreadState();  
  142.             mEGLWindowSurfaceFactory = factory;  
  143.         }  
  144.   
  145.         public void setEGLConfigChooser(EGLConfigChooser configChooser) {  
  146.             checkRenderThreadState();  
  147.             mEGLConfigChooser = configChooser;  
  148.         }  
  149.   
  150.         public void setEGLConfigChooser(boolean needDepth) {  
  151.             setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));  
  152.         }  
  153.   
  154.         public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, int alphaSize, int depthSize,  
  155.                 int stencilSize) {  
  156.             setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, blueSize, alphaSize, depthSize,  
  157.                     stencilSize));  
  158.         }  
  159.   
  160.         public void setRenderMode(int renderMode) {  
  161.             mGLThread.setRenderMode(renderMode);  
  162.         }  
  163.   
  164.         public int getRenderMode() {  
  165.             return mGLThread.getRenderMode();  
  166.         }  
  167.   
  168.         public void requestRender() {  
  169.             mGLThread.requestRender();  
  170.         }  
  171.   
  172.         public void onPause() {  
  173.             mGLThread.onPause();  
  174.         }  
  175.   
  176.         public void onResume() {  
  177.             mGLThread.onResume();  
  178.         }  
  179.   
  180.         public void queueEvent(Runnable r) {  
  181.             mGLThread.queueEvent(r);  
  182.         }  
  183.   
  184.         private void checkRenderThreadState() {  
  185.             if (mGLThread != null) {  
  186.                 throw new IllegalStateException("setRenderer has already been called for this instance.");  
  187.             }  
  188.         }  
  189.     }  
  190.   
  191.     public interface Renderer {  
  192.   
  193.         public void onSurfaceCreated(GL10 gl, EGLConfig config);  
  194.   
  195.         public void onSurfaceChanged(GL10 gl, int width, int height);  
  196.   
  197.         public void onDrawFrame(GL10 gl);  
  198.     }  
  199. }  
  200.   
  201. class LogWriter extends Writer {  
  202.     private StringBuilder mBuilder = new StringBuilder();  
  203.   
  204.     @Override  
  205.     public void close() {  
  206.         flushBuilder();  
  207.     }  
  208.   
  209.     @Override  
  210.     public void flush() {  
  211.         flushBuilder();  
  212.     }  
  213.   
  214.     @Override  
  215.     public void write(char[] buf, int offset, int count) {  
  216.         for (int i = 0; i < count; i++) {  
  217.             char c = buf[offset + i];  
  218.             if (c == '\n') {  
  219.                 flushBuilder();  
  220.             } else {  
  221.                 mBuilder.append(c);  
  222.             }  
  223.         }  
  224.     }  
  225.   
  226.     private void flushBuilder() {  
  227.         if (mBuilder.length() > 0) {  
  228.             Log.v("GLSurfaceView", mBuilder.toString());  
  229.             mBuilder.delete(0, mBuilder.length());  
  230.         }  
  231.     }  
  232. }  
  233.   
  234. // ----------------------------------------------------------------------   
  235.   
  236. /** 
  237.  * An interface for customizing the eglCreateContext and eglDestroyContext calls. 
  238.  * 
  239.  
  240.  * This interface must be implemented by clients wishing to call 
  241.  * {@link GLWallpaperService#setEGLContextFactory(EGLContextFactory)} 
  242.  */  
  243. interface EGLContextFactory {  
  244.     EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig);  
  245.   
  246.     void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);  
  247. }  
  248.   
  249. class DefaultContextFactory implements EGLContextFactory {  
  250.   
  251.     public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {  
  252.         return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null);  
  253.     }  
  254.   
  255.     public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {  
  256.         egl.eglDestroyContext(display, context);  
  257.     }  
  258. }  
  259.   
  260. /** 
  261.  * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. 
  262.  * 
  263.  
  264.  * This interface must be implemented by clients wishing to call 
  265.  * {@link GLWallpaperService#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} 
  266.  */  
  267. interface EGLWindowSurfaceFactory {  
  268.     EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, Object nativeWindow);  
  269.   
  270.     void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface);  
  271. }  
  272.   
  273. class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {  
  274.   
  275.     public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay  
  276.             display, EGLConfig config, Object nativeWindow) {  
  277.         // this is a bit of a hack to work around Droid init problems - if you don't have this, it'll get hung up on orientation changes   
  278.         EGLSurface eglSurface = null;  
  279.         while (eglSurface == null) {  
  280.             try {  
  281.                 eglSurface = egl.eglCreateWindowSurface(display,  
  282.                         config, nativeWindow, null);  
  283.             } catch (Throwable t) {  
  284.             } finally {  
  285.                 if (eglSurface == null) {  
  286.                     try {  
  287.                         Thread.sleep(10);  
  288.                     } catch (InterruptedException t) {  
  289.                     }  
  290.                 }  
  291.             }  
  292.         }  
  293.         return eglSurface;  
  294.     }  
  295.   
  296.     public void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface) {  
  297.         egl.eglDestroySurface(display, surface);  
  298.     }  
  299. }  
  300.   
  301. interface GLWrapper {  
  302.     /** 
  303.      * Wraps a gl interface in another gl interface. 
  304.      * 
  305.      * @param gl 
  306.      * a GL interface that is to be wrapped. 
  307.      * @return either the input argument or another GL object that wraps the input argument. 
  308.      */  
  309.     GL wrap(GL gl);  
  310. }  
  311.   
  312. class EglHelper {  
  313.   
  314.     private EGL10 mEgl;  
  315.     private EGLDisplay mEglDisplay;  
  316.     private EGLSurface mEglSurface;  
  317.     private EGLContext mEglContext;  
  318.     EGLConfig mEglConfig;  
  319.   
  320.     private EGLConfigChooser mEGLConfigChooser;  
  321.     private EGLContextFactory mEGLContextFactory;  
  322.     private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;  
  323.     private GLWrapper mGLWrapper;  
  324.   
  325.     public EglHelper(EGLConfigChooser chooser, EGLContextFactory contextFactory,  
  326.             EGLWindowSurfaceFactory surfaceFactory, GLWrapper wrapper) {  
  327.         this.mEGLConfigChooser = chooser;  
  328.         this.mEGLContextFactory = contextFactory;  
  329.         this.mEGLWindowSurfaceFactory = surfaceFactory;  
  330.         this.mGLWrapper = wrapper;  
  331.     }  
  332.   
  333.     /** 
  334.      * Initialize EGL for a given configuration spec. 
  335.      * 
  336.      * @param configSpec 
  337.      */  
  338.     public void start() {  
  339.         // Log.d("EglHelper" + instanceId, "start()");   
  340.         if (mEgl == null) {  
  341.             // Log.d("EglHelper" + instanceId, "getting new EGL");   
  342.             /* 
  343.              * Get an EGL instance 
  344.              */  
  345.             mEgl = (EGL10) EGLContext.getEGL();  
  346.         } else {  
  347.             // Log.d("EglHelper" + instanceId, "reusing EGL");   
  348.         }  
  349.   
  350.         if (mEglDisplay == null) {  
  351.             // Log.d("EglHelper" + instanceId, "getting new display");   
  352.             /* 
  353.              * Get to the default display. 
  354.              */  
  355.             mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);  
  356.         } else {  
  357.             // Log.d("EglHelper" + instanceId, "reusing display");   
  358.         }  
  359.   
  360.         if (mEglConfig == null) {  
  361.             // Log.d("EglHelper" + instanceId, "getting new config");   
  362.             /* 
  363.              * We can now initialize EGL for that display 
  364.              */  
  365.             int[] version = new int[2];  
  366.             mEgl.eglInitialize(mEglDisplay, version);  
  367.             mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);  
  368.         } else {  
  369.             // Log.d("EglHelper" + instanceId, "reusing config");   
  370.         }  
  371.   
  372.         if (mEglContext == null) {  
  373.             // Log.d("EglHelper" + instanceId, "creating new context");   
  374.             /* 
  375.              * Create an OpenGL ES context. This must be done only once, an OpenGL context is a somewhat heavy object. 
  376.              */  
  377.             mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);  
  378.             if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {  
  379.                 throw new RuntimeException("createContext failed");  
  380.             }  
  381.         } else {  
  382.             // Log.d("EglHelper" + instanceId, "reusing context");   
  383.         }  
  384.   
  385.         mEglSurface = null;  
  386.     }  
  387.   
  388.     /* 
  389.      * React to the creation of a new surface by creating and returning an OpenGL interface that renders to that 
  390.      * surface. 
  391.      */  
  392.     public GL createSurface(SurfaceHolder holder) {  
  393.         /* 
  394.          * The window size has changed, so we need to create a new surface. 
  395.          */  
  396.         if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {  
  397.   
  398.             /* 
  399.              * Unbind and destroy the old EGL surface, if there is one. 
  400.              */  
  401.             mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);  
  402.             mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);  
  403.         }  
  404.   
  405.         /* 
  406.          * Create an EGL surface we can render into. 
  407.          */  
  408.         mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, holder);  
  409.   
  410.         if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {  
  411.             throw new RuntimeException("createWindowSurface failed");  
  412.         }  
  413.   
  414.         /* 
  415.          * Before we can issue GL commands, we need to make sure the context is current and bound to a surface. 
  416.          */  
  417.         if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {  
  418.             throw new RuntimeException("eglMakeCurrent failed.");  
  419.         }  
  420.   
  421.         GL gl = mEglContext.getGL();  
  422.         if (mGLWrapper != null) {  
  423.             gl = mGLWrapper.wrap(gl);  
  424.         }  
  425.   
  426.         /* 
  427.          * if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS))!= 0) { int configFlags = 0; Writer log = 
  428.          * null; if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; } 
  429.          * if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { log = new LogWriter(); } gl = GLDebugHelper.wrap(gl, 
  430.          * configFlags, log); } 
  431.          */  
  432.         return gl;  
  433.     }  
  434.   
  435.     /** 
  436.      * Display the current render surface. 
  437.      * 
  438.      * @return false if the context has been lost. 
  439.      */  
  440.     public boolean swap() {  
  441.         mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);  
  442.   
  443.         /* 
  444.          * Always check for EGL_CONTEXT_LOST, which means the context and all associated data were lost (For instance 
  445.          * because the device went to sleep). We need to sleep until we get a new surface. 
  446.          */  
  447.         return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;  
  448.     }  
  449.   
  450.     public void destroySurface() {  
  451.         if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {  
  452.             mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);  
  453.             mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);  
  454.             mEglSurface = null;  
  455.         }  
  456.     }  
  457.   
  458.     public void finish() {  
  459.         if (mEglContext != null) {  
  460.             mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext);  
  461.             mEglContext = null;  
  462.         }  
  463.         if (mEglDisplay != null) {  
  464.             mEgl.eglTerminate(mEglDisplay);  
  465.             mEglDisplay = null;  
  466.         }  
  467.     }  
  468. }  
  469.   
  470. class GLThread extends Thread {  
  471.     private final static boolean LOG_THREADS = false;  
  472.     public final static int DEBUG_CHECK_GL_ERROR = 1;  
  473.     public final static int DEBUG_LOG_GL_CALLS = 2;  
  474.   
  475.     private final GLThreadManager sGLThreadManager = new GLThreadManager();  
  476.     private GLThread mEglOwner;  
  477.   
  478.     private EGLConfigChooser mEGLConfigChooser;  
  479.     private EGLContextFactory mEGLContextFactory;  
  480.     private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;  
  481.     private GLWrapper mGLWrapper;  
  482.   
  483.     public SurfaceHolder mHolder;  
  484.     private boolean mSizeChanged = true;  
  485.   
  486.     // Once the thread is started, all accesses to the following member   
  487.     // variables are protected by the sGLThreadManager monitor   
  488.     public boolean mDone;  
  489.     private boolean mPaused;  
  490.     private boolean mHasSurface;  
  491.     private boolean mWaitingForSurface;  
  492.     private boolean mHaveEgl;  
  493.     private int mWidth;  
  494.     private int mHeight;  
  495.     private int mRenderMode;  
  496.     private boolean mRequestRender;  
  497.     private boolean mEventsWaiting;  
  498.     // End of member variables protected by the sGLThreadManager monitor.   
  499.   
  500.     private GLWallpaperService.Renderer mRenderer;  
  501.     private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();  
  502.     private EglHelper mEglHelper;  
  503.   
  504.     GLThread(GLWallpaperService.Renderer renderer, EGLConfigChooser chooser, EGLContextFactory contextFactory,  
  505.             EGLWindowSurfaceFactory surfaceFactory, GLWrapper wrapper) {  
  506.         super();  
  507.         mDone = false;  
  508.         mWidth = 0;  
  509.         mHeight = 0;  
  510.         mRequestRender = true;  
  511.         mRenderMode = GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY;  
  512.         mRenderer = renderer;  
  513.         this.mEGLConfigChooser = chooser;  
  514.         this.mEGLContextFactory = contextFactory;  
  515.         this.mEGLWindowSurfaceFactory = surfaceFactory;  
  516.         this.mGLWrapper = wrapper;  
  517.     }  
  518.   
  519.     @Override  
  520.     public void run() {  
  521.         setName("GLThread " + getId());  
  522.         if (LOG_THREADS) {  
  523.             Log.i("GLThread""starting tid=" + getId());  
  524.         }  
  525.   
  526.         try {  
  527.             guardedRun();  
  528.         } catch (InterruptedException e) {  
  529.             // fall thru and exit normally   
  530.         } finally {  
  531.             sGLThreadManager.threadExiting(this);  
  532.         }  
  533.     }  
  534.   
  535.     /* 
  536.      * This private method should only be called inside a synchronized(sGLThreadManager) block. 
  537.      */  
  538.     private void stopEglLocked() {  
  539.         if (mHaveEgl) {  
  540.             mHaveEgl = false;  
  541.             mEglHelper.destroySurface();  
  542.             sGLThreadManager.releaseEglSurface(this);  
  543.         }  
  544.     }  
  545.   
  546.     private void guardedRun() throws InterruptedException {  
  547.         mEglHelper = new EglHelper(mEGLConfigChooser, mEGLContextFactory, mEGLWindowSurfaceFactory, mGLWrapper);  
  548.         try {  
  549.             GL10 gl = null;  
  550.             boolean tellRendererSurfaceCreated = true;  
  551.             boolean tellRendererSurfaceChanged = true;  
  552.   
  553.             /* 
  554.              * This is our main activity thread's loop, we go until asked to quit. 
  555.              */  
  556.             while (!isDone()) {  
  557.                 /* 
  558.                  * Update the asynchronous state (window size) 
  559.                  */  
  560.                 int w = 0;  
  561.                 int h = 0;  
  562.                 boolean changed = false;  
  563.                 boolean needStart = false;  
  564.                 boolean eventsWaiting = false;  
  565.   
  566.                 synchronized (sGLThreadManager) {  
  567.                     while (true) {  
  568.                         // Manage acquiring and releasing the SurfaceView   
  569.                         // surface and the EGL surface.   
  570.                         if (mPaused) {  
  571.                             stopEglLocked();  
  572.                         }  
  573.                         if (!mHasSurface) {  
  574.                             if (!mWaitingForSurface) {  
  575.                                 stopEglLocked();  
  576.                                 mWaitingForSurface = true;  
  577.                                 sGLThreadManager.notifyAll();  
  578.                             }  
  579.                         } else {  
  580.                             if (!mHaveEgl) {  
  581.                                 if (sGLThreadManager.tryAcquireEglSurface(this)) {  
  582.                                     mHaveEgl = true;  
  583.                                     mEglHelper.start();  
  584.                                     mRequestRender = true;  
  585.                                     needStart = true;  
  586.                                 }  
  587.                             }  
  588.                         }  
  589.   
  590.                         // Check if we need to wait. If not, update any state   
  591.                         // that needs to be updated, copy any state that   
  592.                         // needs to be copied, and use "break" to exit the   
  593.                         // wait loop.   
  594.   
  595.                         if (mDone) {  
  596.                             return;  
  597.                         }  
  598.   
  599.                         if (mEventsWaiting) {  
  600.                             eventsWaiting = true;  
  601.                             mEventsWaiting = false;  
  602.                             break;  
  603.                         }  
  604.   
  605.                         if ((!mPaused) && mHasSurface && mHaveEgl && (mWidth > 0) && (mHeight > 0)  
  606.                                 && (mRequestRender || (mRenderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) {  
  607.                             changed = mSizeChanged;  
  608.                             w = mWidth;  
  609.                             h = mHeight;  
  610.                             mSizeChanged = false;  
  611.                             mRequestRender = false;  
  612.                             if (mHasSurface && mWaitingForSurface) {  
  613.                                 changed = true;  
  614.                                 mWaitingForSurface = false;  
  615.                                 sGLThreadManager.notifyAll();  
  616.                             }  
  617.                             break;  
  618.                         }  
  619.   
  620.                         // By design, this is the only place where we wait().   
  621.   
  622.                         if (LOG_THREADS) {  
  623.                             Log.i("GLThread""waiting tid=" + getId());  
  624.                         }  
  625.                         sGLThreadManager.wait();  
  626.                     }  
  627.                 } // end of synchronized(sGLThreadManager)   
  628.   
  629.                 /* 
  630.                  * Handle queued events 
  631.                  */  
  632.                 if (eventsWaiting) {  
  633.                     Runnable r;  
  634.                     while ((r = getEvent()) != null) {  
  635.                         r.run();  
  636.                         if (isDone()) {  
  637.                             return;  
  638.                         }  
  639.                     }  
  640.                     // Go back and see if we need to wait to render.   
  641.                     continue;  
  642.                 }  
  643.   
  644.                 if (needStart) {  
  645.                     tellRendererSurfaceCreated = true;  
  646.                     changed = true;  
  647.                 }  
  648.                 if (changed) {  
  649.                     gl = (GL10) mEglHelper.createSurface(mHolder);  
  650.                     tellRendererSurfaceChanged = true;  
  651.                 }  
  652.                 if (tellRendererSurfaceCreated) {  
  653.                     mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);  
  654.                     tellRendererSurfaceCreated = false;  
  655.                 }  
  656.                 if (tellRendererSurfaceChanged) {  
  657.                     mRenderer.onSurfaceChanged(gl, w, h);  
  658.                     tellRendererSurfaceChanged = false;  
  659.                 }  
  660.                 if ((w > 0) && (h > 0)) {  
  661.                     /* draw a frame here */  
  662.                     mRenderer.onDrawFrame(gl);  
  663.   
  664.                     /* 
  665.                      * Once we're done with GL, we need to call swapBuffers() to instruct the system to display the 
  666.                      * rendered frame 
  667.                      */  
  668.                     mEglHelper.swap();  
  669.                     Thread.sleep(10);  
  670.                 }  
  671.             }  
  672.         } finally {  
  673.             /* 
  674.              * clean-up everything... 
  675.              */  
  676.             synchronized (sGLThreadManager) {  
  677.                 stopEglLocked();  
  678.                 mEglHelper.finish();  
  679.             }  
  680.         }  
  681.     }  
  682.   
  683.     private boolean isDone() {  
  684.         synchronized (sGLThreadManager) {  
  685.             return mDone;  
  686.         }  
  687.     }  
  688.   
  689.     public void setRenderMode(int renderMode) {  
  690.         if (!((GLWallpaperService.GLEngine.RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) {  
  691.             throw new IllegalArgumentException("renderMode");  
  692.         }  
  693.         synchronized (sGLThreadManager) {  
  694.             mRenderMode = renderMode;  
  695.             if (renderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY) {  
  696.                 sGLThreadManager.notifyAll();  
  697.             }  
  698.         }  
  699.     }  
  700.   
  701.     public int getRenderMode() {  
  702.         synchronized (sGLThreadManager) {  
  703.             return mRenderMode;  
  704.         }  
  705.     }  
  706.   
  707.     public void requestRender() {  
  708.         synchronized (sGLThreadManager) {  
  709.             mRequestRender = true;  
  710.             sGLThreadManager.notifyAll();  
  711.         }  
  712.     }  
  713.   
  714.     public void surfaceCreated(SurfaceHolder holder) {  
  715.         mHolder = holder;  
  716.         synchronized (sGLThreadManager) {  
  717.             if (LOG_THREADS) {  
  718.                 Log.i("GLThread""surfaceCreated tid=" + getId());  
  719.             }  
  720.             mHasSurface = true;  
  721.             sGLThreadManager.notifyAll();  
  722.         }  
  723.     }  
  724.   
  725.     public void surfaceDestroyed() {  
  726.         synchronized (sGLThreadManager) {  
  727.             if (LOG_THREADS) {  
  728.                 Log.i("GLThread""surfaceDestroyed tid=" + getId());  
  729.             }  
  730.             mHasSurface = false;  
  731.             sGLThreadManager.notifyAll();  
  732.             while (!mWaitingForSurface && isAlive() && !mDone) {  
  733.                 try {  
  734.                     sGLThreadManager.wait();  
  735.                 } catch (InterruptedException e) {  
  736.                     Thread.currentThread().interrupt();  
  737.                 }  
  738.             }  
  739.         }  
  740.     }  
  741.   
  742.     public void onPause() {  
  743.         synchronized (sGLThreadManager) {  
  744.             mPaused = true;  
  745.             sGLThreadManager.notifyAll();  
  746.         }  
  747.     }  
  748.   
  749.     public void onResume() {  
  750.         synchronized (sGLThreadManager) {  
  751.             mPaused = false;  
  752.             mRequestRender = true;  
  753.             sGLThreadManager.notifyAll();  
  754.         }  
  755.     }  
  756.   
  757.     public void onWindowResize(int w, int h) {  
  758.         synchronized (sGLThreadManager) {  
  759.             mWidth = w;  
  760.             mHeight = h;  
  761.             mSizeChanged = true;  
  762.             sGLThreadManager.notifyAll();  
  763.         }  
  764.     }  
  765.   
  766.     public void requestExitAndWait() {  
  767.         // don't call this from GLThread thread or it is a guaranteed   
  768.         // deadlock!   
  769.         synchronized (sGLThreadManager) {  
  770.             mDone = true;  
  771.             sGLThreadManager.notifyAll();  
  772.         }  
  773.         try {  
  774.             join();  
  775.         } catch (InterruptedException ex) {  
  776.             Thread.currentThread().interrupt();  
  777.         }  
  778.     }  
  779.   
  780.     /** 
  781.      * Queue an "event" to be run on the GL rendering thread. 
  782.      * 
  783.      * @param r 
  784.      * the runnable to be run on the GL rendering thread. 
  785.      */  
  786.     public void queueEvent(Runnable r) {  
  787.         synchronized (this) {  
  788.             mEventQueue.add(r);  
  789.             synchronized (sGLThreadManager) {  
  790.                 mEventsWaiting = true;  
  791.                 sGLThreadManager.notifyAll();  
  792.             }  
  793.         }  
  794.     }  
  795.   
  796.     private Runnable getEvent() {  
  797.         synchronized (this) {  
  798.             if (mEventQueue.size() > 0) {  
  799.                 return mEventQueue.remove(0);  
  800.             }  
  801.   
  802.         }  
  803.         return null;  
  804.     }  
  805.   
  806.     private class GLThreadManager {  
  807.   
  808.         public synchronized void threadExiting(GLThread thread) {  
  809.             if (LOG_THREADS) {  
  810.                 Log.i("GLThread""exiting tid=" + thread.getId());  
  811.             }  
  812.             thread.mDone = true;  
  813.             if (mEglOwner == thread) {  
  814.                 mEglOwner = null;  
  815.             }  
  816.             notifyAll();  
  817.         }  
  818.   
  819.         /* 
  820.          * Tries once to acquire the right to use an EGL surface. Does not block. 
  821.          * 
  822.          * @return true if the right to use an EGL surface was acquired. 
  823.          */  
  824.         public synchronized boolean tryAcquireEglSurface(GLThread thread) {  
  825.             if (mEglOwner == thread || mEglOwner == null) {  
  826.                 mEglOwner = thread;  
  827.                 notifyAll();  
  828.                 return true;  
  829.             }  
  830.             return false;  
  831.         }  
  832.   
  833.         public synchronized void releaseEglSurface(GLThread thread) {  
  834.             if (mEglOwner == thread) {  
  835.                 mEglOwner = null;  
  836.             }  
  837.             notifyAll();  
  838.         }  
  839.     }  
  840. }  
  841.   
  842. interface EGLConfigChooser {  
  843.     EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);  
  844. }  
  845.   
  846. abstract class BaseConfigChooser implements EGLConfigChooser {  
  847.     public BaseConfigChooser(int[] configSpec) {  
  848.         mConfigSpec = configSpec;  
  849.     }  
  850.   
  851.     public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {  
  852.         int[] num_config = new int[1];  
  853.         egl.eglChooseConfig(display, mConfigSpec, null0, num_config);  
  854.   
  855.         int numConfigs = num_config[0];  
  856.   
  857.         if (numConfigs <= 0) {  
  858.             throw new IllegalArgumentException("No configs match configSpec");  
  859.         }  
  860.   
  861.         EGLConfig[] configs = new EGLConfig[numConfigs];  
  862.         egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, num_config);  
  863.         EGLConfig config = chooseConfig(egl, display, configs);  
  864.         if (config == null) {  
  865.             throw new IllegalArgumentException("No config chosen");  
  866.         }  
  867.         return config;  
  868.     }  
  869.   
  870.     abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs);  
  871.   
  872.     protected int[] mConfigSpec;  
  873.     public static class ComponentSizeChooser extends BaseConfigChooser {  
  874.         public ComponentSizeChooser(int redSize, int greenSize, int blueSize, int alphaSize, int depthSize,  
  875.                 int stencilSize) {  
  876.             super(new int[] { EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_BLUE_SIZE,  
  877.                     blueSize, EGL10.EGL_ALPHA_SIZE, alphaSize, EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_STENCIL_SIZE,  
  878.                     stencilSize, EGL10.EGL_NONE });  
  879.             mValue = new int[1];  
  880.             mRedSize = redSize;  
  881.             mGreenSize = greenSize;  
  882.             mBlueSize = blueSize;  
  883.             mAlphaSize = alphaSize;  
  884.             mDepthSize = depthSize;  
  885.             mStencilSize = stencilSize;  
  886.         }  
  887.   
  888.         @Override  
  889.         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {  
  890.             EGLConfig closestConfig = null;  
  891.             int closestDistance = 1000;  
  892.             for (EGLConfig config : configs) {  
  893.                 int d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);  
  894.                 int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);  
  895.                 if (d >= mDepthSize && s >= mStencilSize) {  
  896.                     int r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);  
  897.                     int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);  
  898.                     int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);  
  899.                     int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);  
  900.                     int distance = Math.abs(r - mRedSize) + Math.abs(g - mGreenSize) + Math.abs(b - mBlueSize)  
  901.                     + Math.abs(a - mAlphaSize);  
  902.                     if (distance < closestDistance) {  
  903.                         closestDistance = distance;  
  904.                         closestConfig = config;  
  905.                     }  
  906.                 }  
  907.             }  
  908.             return closestConfig;  
  909.         }  
  910.   
  911.         private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue) {  
  912.   
  913.             if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {  
  914.                 return mValue[0];  
  915.             }  
  916.             return defaultValue;  
  917.         }  
  918.   
  919.         private int[] mValue;  
  920.         // Subclasses can adjust these values:   
  921.         protected int mRedSize;  
  922.         protected int mGreenSize;  
  923.         protected int mBlueSize;  
  924.         protected int mAlphaSize;  
  925.         protected int mDepthSize;  
  926.         protected int mStencilSize;  
  927.     }  
  928.   
  929.     /** 
  930.      * This class will choose a supported surface as close to RGB565 as possible, with or without a depth buffer. 
  931.      * 
  932.      */  
  933.     public static class SimpleEGLConfigChooser extends ComponentSizeChooser {  
  934.         public SimpleEGLConfigChooser(boolean withDepthBuffer) {  
  935.             super(4440, withDepthBuffer ? 16 : 00);  
  936.             // Adjust target values. This way we'll accept a 4444 or   
  937.             // 555 buffer if there's no 565 buffer available.   
  938.             mRedSize = 5;  
  939.             mGreenSize = 6;  
  940.             mBlueSize = 5;  
  941.         }  
  942.     }  

相关内容