Advertisement
Guest User

GLWallpaper with GL ES 2.0 Support

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