First blood
This commit is contained in:
1 parent
172a38114f
commit
3f3c1735d6
65 files changed
+2853
No files matched your search
@@ -0,0 +1,960 @@
|
||||
package fishrungames.mountainwallpaper;
|
||||
|
||||
|
||||
import fishrungames.mountainwallpaper.BaseConfigChooser.ComponentSizeChooser;
|
||||
import fishrungames.mountainwallpaper.BaseConfigChooser.SimpleEGLConfigChooser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.egl.EGLContext;
|
||||
import javax.microedition.khronos.egl.EGLDisplay;
|
||||
import javax.microedition.khronos.egl.EGLSurface;
|
||||
|
||||
|
||||
import android.service.wallpaper.WallpaperService;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
import fishrungames.engine.EngineWrapper;
|
||||
|
||||
|
||||
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 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);
|
||||
// Log.d(TAG, "GLEngine.onCreate()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
// Log.d(TAG, "GLEngine.onDestroy()");
|
||||
mGLThread.requestExitAndWait();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged(SurfaceHolder holder, int format,
|
||||
int width, int height) {
|
||||
// Log.d(TAG, "onSurfaceChanged()");
|
||||
|
||||
|
||||
|
||||
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 setDebugFlags(int debugFlags) {
|
||||
mDebugFlags = debugFlags;
|
||||
}
|
||||
|
||||
public int getDebugFlags() {
|
||||
return mDebugFlags;
|
||||
}
|
||||
|
||||
public void setRenderer() {
|
||||
checkRenderThreadState();
|
||||
if (mEGLConfigChooser == null) {
|
||||
mEGLConfigChooser = new SimpleEGLConfigChooser(true);
|
||||
}
|
||||
if (mEGLContextFactory == null) {
|
||||
//mEGLContextFactory = new DefaultContextFactory();
|
||||
mEGLContextFactory = new ES20ContextFactory();
|
||||
}
|
||||
if (mEGLWindowSurfaceFactory == null) {
|
||||
mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
|
||||
}
|
||||
mGLThread = new GLThread(mEGLConfigChooser,
|
||||
mEGLContextFactory, mEGLWindowSurfaceFactory);
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* An interface for customizing the eglCreateContext and eglDestroyContext
|
||||
* calls.
|
||||
*
|
||||
*
|
||||
* This interface must be implemented by clients wishing to call
|
||||
* {@link GLWallpaperService#setEGLContextFactory(EGLContextFactory)}
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ES20ContextFactory implements EGLContextFactory {
|
||||
|
||||
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
|
||||
public EGLContext createContext(EGL10 egl, EGLDisplay display,
|
||||
EGLConfig config) {
|
||||
|
||||
|
||||
int[] attrib_list =
|
||||
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
|
||||
|
||||
return egl
|
||||
.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, attrib_list);
|
||||
}
|
||||
|
||||
public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
|
||||
egl.eglDestroyContext(display, context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for customizing the eglCreateWindowSurface and eglDestroySurface
|
||||
* calls.
|
||||
*
|
||||
*
|
||||
* This interface must be implemented by clients wishing to call
|
||||
* {@link GLWallpaperService#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)}
|
||||
*/
|
||||
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) {
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
public EglHelper(EGLConfigChooser chooser,
|
||||
EGLContextFactory contextFactory,
|
||||
EGLWindowSurfaceFactory surfaceFactory) {
|
||||
this.mEGLConfigChooser = chooser;
|
||||
this.mEGLContextFactory = contextFactory;
|
||||
this.mEGLWindowSurfaceFactory = surfaceFactory;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize EGL for a given configuration spec.
|
||||
*
|
||||
* @param configSpec
|
||||
*/
|
||||
public void start() {
|
||||
String instanceId = "";
|
||||
Log.d("EglHelper" + instanceId, "start()");
|
||||
if (mEgl == null) {
|
||||
Log.d("EglHelper" + instanceId, "getting new EGL");
|
||||
/*
|
||||
* Get an EGL instance
|
||||
*/
|
||||
mEgl = (EGL10) EGLContext.getEGL();
|
||||
} else {
|
||||
Log.d("EglHelper" + instanceId, "reusing EGL");
|
||||
}
|
||||
|
||||
if (mEglDisplay == null) {
|
||||
Log.d("EglHelper" + instanceId, "getting new display");
|
||||
/*
|
||||
* Get to the default display.
|
||||
*/
|
||||
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
} else {
|
||||
Log.d("EglHelper" + instanceId, "reusing display");
|
||||
}
|
||||
|
||||
if (mEglConfig == null) {
|
||||
Log.d("EglHelper" + instanceId, "getting new config");
|
||||
/*
|
||||
* We can now initialize EGL for that display
|
||||
*/
|
||||
int[] version = new int[2];
|
||||
mEgl.eglInitialize(mEglDisplay, version);
|
||||
mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
|
||||
} else {
|
||||
Log.d("EglHelper" + instanceId, "reusing config");
|
||||
}
|
||||
|
||||
if (mEglContext == null) {
|
||||
Log.d("EglHelper" + instanceId, "creating new context");
|
||||
/*
|
||||
* Create an OpenGL ES context. This must be done only once, an
|
||||
* OpenGL context is a somewhat heavy object.
|
||||
*/
|
||||
mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay,
|
||||
mEglConfig);
|
||||
if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
|
||||
throw new RuntimeException("createContext failed");
|
||||
}
|
||||
} else {
|
||||
Log.d("EglHelper" + instanceId, "reusing context");
|
||||
}
|
||||
|
||||
mEglSurface = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* React to the creation of a new surface by creating and returning an
|
||||
* OpenGL interface that renders to that surface.
|
||||
*/
|
||||
|
||||
|
||||
public void 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.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the current render surface.
|
||||
*
|
||||
* @return false if the context has been lost.
|
||||
*/
|
||||
public boolean swap() {
|
||||
try {
|
||||
mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
/*
|
||||
* Always check for EGL_CONTEXT_LOST, which means the context and all
|
||||
* associated data were lost (For instance because the device went to
|
||||
* sleep). We need to sleep until we get a new surface.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
public SurfaceHolder mHolder;
|
||||
private boolean mSizeChanged = true;
|
||||
|
||||
// Once the thread is started, all accesses to the following member
|
||||
// variables are protected by the sGLThreadManager monitor
|
||||
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;
|
||||
// End of member variables protected by the sGLThreadManager monitor.
|
||||
|
||||
//private GLWallpaperService.Renderer mRenderer;
|
||||
|
||||
private ArrayList mEventQueue = new ArrayList();
|
||||
private EglHelper mEglHelper;
|
||||
|
||||
|
||||
static long lastTimeStamp;
|
||||
static boolean gameIsInited = false;
|
||||
|
||||
GLThread(EGLConfigChooser chooser,
|
||||
EGLContextFactory contextFactory,
|
||||
EGLWindowSurfaceFactory surfaceFactory) {
|
||||
super();
|
||||
mDone = false;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mRequestRender = true;
|
||||
mRenderMode = GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY;
|
||||
|
||||
this.mEGLConfigChooser = chooser;
|
||||
this.mEGLContextFactory = contextFactory;
|
||||
this.mEGLWindowSurfaceFactory = surfaceFactory;
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
lastTimeStamp = c.getTimeInMillis();
|
||||
gameIsInited = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
setName("GLThread " + getId());
|
||||
if (LOG_THREADS) {
|
||||
Log.i("GLThread", "starting tid=" + getId());
|
||||
}
|
||||
|
||||
try {
|
||||
guardedRun();
|
||||
} catch (InterruptedException e) {
|
||||
// fall thru and exit normally
|
||||
} finally {
|
||||
sGLThreadManager.threadExiting(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This private method should only be called inside a
|
||||
* synchronized(sGLThreadManager) block.
|
||||
*/
|
||||
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 {
|
||||
|
||||
boolean tellRendererSurfaceCreated = true;
|
||||
boolean tellRendererSurfaceChanged = true;
|
||||
|
||||
/*
|
||||
* This is our main activity thread's loop, we go until asked to
|
||||
* quit.
|
||||
*/
|
||||
while (!isDone()) {
|
||||
/*
|
||||
* Update the asynchronous state (window size)
|
||||
*/
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
boolean changed = false;
|
||||
boolean needStart = false;
|
||||
boolean eventsWaiting = false;
|
||||
|
||||
synchronized (sGLThreadManager) {
|
||||
while (true) {
|
||||
// Manage acquiring and releasing the SurfaceView
|
||||
// surface and the EGL surface.
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we need to wait. If not, update any state
|
||||
// that needs to be updated, copy any state that
|
||||
// needs to be copied, and use "break" to exit the
|
||||
// wait loop.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// By design, this is the only place where we wait().
|
||||
|
||||
if (LOG_THREADS) {
|
||||
Log.i("GLThread", "waiting tid=" + getId());
|
||||
}
|
||||
sGLThreadManager.wait();
|
||||
}
|
||||
} // end of synchronized(sGLThreadManager)
|
||||
|
||||
/*
|
||||
* Handle queued events
|
||||
*/
|
||||
if (eventsWaiting) {
|
||||
Runnable r;
|
||||
while ((r = getEvent()) != null) {
|
||||
r.run();
|
||||
if (isDone()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Go back and see if we need to wait to render.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (needStart) {
|
||||
tellRendererSurfaceCreated = true;
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
mEglHelper.createSurface(mHolder);
|
||||
tellRendererSurfaceChanged = true;
|
||||
}
|
||||
if (tellRendererSurfaceCreated) {
|
||||
|
||||
tellRendererSurfaceCreated = false;
|
||||
}
|
||||
|
||||
if (tellRendererSurfaceChanged) {
|
||||
|
||||
|
||||
//Xperimental -- VLAD KHOREV
|
||||
JniWrapper.Init(w, h);
|
||||
|
||||
tellRendererSurfaceChanged = false;
|
||||
}
|
||||
|
||||
|
||||
if ((w > 0) && (h > 0)) {
|
||||
/* draw a frame here */
|
||||
|
||||
if (gameIsInited)
|
||||
{
|
||||
Calendar c = Calendar.getInstance();
|
||||
|
||||
long currentTimeStamp = c.getTimeInMillis();
|
||||
|
||||
EngineWrapper.Update(currentTimeStamp - lastTimeStamp);
|
||||
|
||||
lastTimeStamp = currentTimeStamp;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Once we're done with GL, we need to call swapBuffers() to
|
||||
* instruct the system to display the rendered frame
|
||||
*/
|
||||
mEglHelper.swap();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
/*
|
||||
* clean-up everything...
|
||||
*/
|
||||
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() {
|
||||
// don't call this from GLThread thread or it is a guaranteed
|
||||
// deadlock!
|
||||
synchronized (sGLThreadManager) {
|
||||
mDone = true;
|
||||
sGLThreadManager.notifyAll();
|
||||
}
|
||||
try {
|
||||
join();
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue an "event" to be run on the GL rendering thread.
|
||||
*
|
||||
* @param r
|
||||
* the runnable to be run on the GL rendering thread.
|
||||
*/
|
||||
public void queueEvent(Runnable r) {
|
||||
synchronized (this) {
|
||||
mEventQueue.add(r);
|
||||
synchronized (sGLThreadManager) {
|
||||
mEventsWaiting = true;
|
||||
sGLThreadManager.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable getEvent() {
|
||||
synchronized (this) {
|
||||
if (mEventQueue.size() > 0) {
|
||||
return (Runnable) 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();
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries once to acquire the right to use an EGL surface. Does not
|
||||
* block.
|
||||
*
|
||||
* @return true if the right to use an EGL surface was acquired.
|
||||
*/
|
||||
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;
|
||||
// Subclasses can adjust these values:
|
||||
protected int mRedSize;
|
||||
protected int mGreenSize;
|
||||
protected int mBlueSize;
|
||||
protected int mAlphaSize;
|
||||
protected int mDepthSize;
|
||||
protected int mStencilSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class will choose a supported surface as close to RGB565 as
|
||||
* possible, with or without a depth buffer.
|
||||
*
|
||||
*/
|
||||
public static class SimpleEGLConfigChooser extends ComponentSizeChooser {
|
||||
public SimpleEGLConfigChooser(boolean withDepthBuffer) {
|
||||
super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);
|
||||
// Adjust target values. This way we'll accept a 4444 or
|
||||
// 555 buffer if there's no 565 buffer available.
|
||||
mRedSize = 5;
|
||||
mGreenSize = 6;
|
||||
mBlueSize = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package fishrungames.mountainwallpaper;
|
||||
|
||||
public class JniWrapper
|
||||
{
|
||||
|
||||
static
|
||||
{
|
||||
System.loadLibrary("SalmonWallpaper");
|
||||
}
|
||||
|
||||
public static void LoadLibrary()
|
||||
{
|
||||
//To force loading libraries
|
||||
}
|
||||
|
||||
public static native void SetTimeOfDayPref(int timeofday);
|
||||
|
||||
public static native void SetSnowPref(boolean snow);
|
||||
|
||||
|
||||
public static native void Init(int width, int height);
|
||||
|
||||
public static native void SetOffset(float offsetX, float offsetY);
|
||||
|
||||
public static native void SetOrientation(int isLandscape);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package fishrungames.mountainwallpaper;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
|
||||
import android.net.ConnectivityManager;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
//import com.seb.SLWP.SLWP.GlEngine.DownloadTask;
|
||||
|
||||
import fishrungames.engine.EngineWrapper;
|
||||
|
||||
public class MountainWallpaperService extends GLWallpaperService implements
|
||||
OnSharedPreferenceChangeListener {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.app.Service#onLowMemory()
|
||||
*/
|
||||
static
|
||||
{
|
||||
EngineWrapper.LoadSalmonEngineLibrary();
|
||||
JniWrapper.LoadLibrary();
|
||||
}
|
||||
|
||||
|
||||
public static final long SLEEPTIME = 1000 * 60 * 30; // 30 minutes
|
||||
private GlEngine mGle;
|
||||
|
||||
public static Context mContext;
|
||||
public static boolean ShowClouds;
|
||||
public static boolean TouchRot;
|
||||
|
||||
public static int Bg;
|
||||
public static boolean Usebg;
|
||||
public static int Tex;
|
||||
|
||||
static long Synctime;
|
||||
|
||||
public boolean Slidedir;
|
||||
public boolean Slideplanet;
|
||||
public boolean Syncrot;
|
||||
public static boolean Randomtex = true;
|
||||
public static boolean visible = false;
|
||||
|
||||
public static boolean useCropper = true;
|
||||
public static int Cropaspect;
|
||||
public static boolean loading = false;
|
||||
|
||||
public static final Handler mHandler = new Handler();
|
||||
public static final int RNDMAP = -1;
|
||||
public static boolean destroyed;
|
||||
public static String bgfile;
|
||||
public ConnectivityManager cm;
|
||||
public boolean needresume;
|
||||
public boolean fstart;
|
||||
public static String[] randlist;
|
||||
public int curtexidx = -99;
|
||||
|
||||
static final String ACTION_FOREGROUND = "fishrungames.mountainwallpaper.FOREGROUND";
|
||||
static final String ACTION_BACKGROUND = "fishrungames.mountainwallpaper.BACKGROUND";
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onCreate();
|
||||
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
EngineWrapper.SetActivityInstance(this);
|
||||
EngineWrapper.SetupEnviroment();
|
||||
|
||||
String apkFilePath = null;
|
||||
ApplicationInfo appInfo = null;
|
||||
PackageManager packMgmr = this.getPackageManager();
|
||||
try {
|
||||
appInfo = packMgmr.getApplicationInfo("fishrungames.mountainwallpaper", 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
|
||||
|
||||
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Unable to locate assets, aborting...");
|
||||
}
|
||||
apkFilePath = appInfo.sourceDir;
|
||||
|
||||
EngineWrapper.SetupApkFilePath(apkFilePath);
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// handleCommand(intent);
|
||||
// We want this service to continue running until it is explicitly
|
||||
// stopped, so return sticky.
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
private void Init() {
|
||||
try {
|
||||
mContext = this;
|
||||
cm = (ConnectivityManager) mContext
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||
String key) {
|
||||
|
||||
if (key.compareToIgnoreCase("Timeofday") == 0)
|
||||
{
|
||||
int time = Integer.parseInt(sharedPreferences.getString("Timeofday", "0"));
|
||||
JniWrapper.SetTimeOfDayPref(time);
|
||||
}
|
||||
|
||||
if (key.compareToIgnoreCase("Snow") == 0) {
|
||||
|
||||
JniWrapper.SetSnowPref(sharedPreferences.getBoolean("Snow", false));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine onCreateEngine() {
|
||||
if (mGle != null) {
|
||||
mGle = null;
|
||||
}
|
||||
try {
|
||||
|
||||
mGle = new GlEngine();
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mGle;
|
||||
}
|
||||
|
||||
class GlEngine extends GLEngine {
|
||||
|
||||
public Handler mHandler = new Handler();
|
||||
|
||||
long NOW;
|
||||
|
||||
@Override
|
||||
public void onCreate(SurfaceHolder surfaceHolder) {
|
||||
super.onCreate(surfaceHolder);
|
||||
try {
|
||||
this.setTouchEventsEnabled(true);
|
||||
fstart = true;
|
||||
setRenderer();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouchEvent(MotionEvent e) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOffsetsChanged(float xOffset, float yOffset,
|
||||
float xOffsetStep, float yOffsetStep, int xPixelOffset,
|
||||
int yPixelOffset) {
|
||||
|
||||
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
|
||||
xPixelOffset, yPixelOffset);
|
||||
|
||||
JniWrapper.SetOffset(xPixelOffset*xOffsetStep, yPixelOffset*yOffsetStep);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVisibilityChanged(boolean visible) {
|
||||
// TODO Auto-generated method stub
|
||||
super.onVisibilityChanged(visible);
|
||||
MountainWallpaperService.visible = visible;
|
||||
if (visible) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged(SurfaceHolder holder, int format,
|
||||
int width, int height) {
|
||||
// TODO Auto-generated method stub
|
||||
super.onSurfaceChanged(holder, format, width, height);
|
||||
fstart = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package fishrungames.mountainwallpaper;
|
||||
|
||||
import fishrungames.mountainwallpaper.R;
|
||||
import fishrungames.mountainwallpaper.JniWrapper;
|
||||
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
|
||||
|
||||
public class Prefs extends PreferenceActivity implements
|
||||
OnPreferenceChangeListener {
|
||||
|
||||
|
||||
private CheckBoxPreference snowPref;
|
||||
private ListPreference timeOfDayPref;
|
||||
|
||||
|
||||
public static Uri currImageURI;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.prefliste);
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
|
||||
snowPref = (CheckBoxPreference)this.getPreferenceManager().findPreference("Snow");
|
||||
timeOfDayPref = (ListPreference) findPreference("Timeofday");
|
||||
|
||||
if (timeOfDayPref.getKey().compareToIgnoreCase("Timeofday") == 0)
|
||||
{
|
||||
JniWrapper.SetTimeOfDayPref(Integer.parseInt((String) timeOfDayPref.getValue()));
|
||||
|
||||
}
|
||||
|
||||
if (snowPref.getKey().compareToIgnoreCase("Snow") == 0) {
|
||||
if (!snowPref.isChecked())
|
||||
{
|
||||
JniWrapper.SetSnowPref(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
JniWrapper.SetSnowPref(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user