package com.example.android.image3D; |
import android.view.SurfaceView; |
import android.view.SurfaceHolder; |
import android.content.Context; |
import android.util.AttributeSet; |
import java.util.ArrayList; |
import java.util.concurrent.Semaphore; |
import javax.microedition.khronos.egl.EGL10; |
import javax.microedition.khronos.egl.EGL11; |
import javax.microedition.khronos.egl.EGLConfig; |
import javax.microedition.khronos.egl.EGLContext; |
import javax.microedition.khronos.egl.EGLDisplay; |
import javax.microedition.khronos.egl.EGLSurface; |
import javax.microedition.khronos.opengles.GL; |
import javax.microedition.khronos.opengles.GL10; |
public class View3D extends SurfaceView implements SurfaceHolder.Callback { |
private static final Semaphore sEglSemaphore = new Semaphore ( 1 ); |
private boolean mSizeChanged = true ; |
private SurfaceHolder mHolder; |
private GLThread mGLThread; |
private GLWrapper mGLWrapper; |
public View3D (Context context) { |
super (context); |
init(); |
} |
public View3D (Context context, AttributeSet attrs) { |
super (context, attrs); |
init(); |
} |
private void init() { |
mHolder = getHolder(); |
mHolder.addCallback ( this ); |
mHolder.setType (SurfaceHolder.SURFACE_TYPE_GPU); |
} |
public SurfaceHolder getSurfaceHolder() { |
return mHolder; |
} |
public void setGLWrapper (GLWrapper glWrapper) { |
mGLWrapper = glWrapper; |
} |
public void setRenderer (Renderer renderer) { |
mGLThread = new GLThread (renderer); |
mGLThread.start(); |
} |
public void surfaceCreated (SurfaceHolder holder) { |
mGLThread.surfaceCreated(); |
} |
public void surfaceDestroyed (SurfaceHolder holder) { |
mGLThread.surfaceDestroyed(); |
} |
public void surfaceChanged (SurfaceHolder holder, |
int format, int w, int h) { |
mGLThread.onWindowResize (w, h); |
} |
public void onPause() { |
mGLThread.onPause(); |
} |
public void onResume() { |
mGLThread.onResume(); |
} |
@Override |
public void onWindowFocusChanged ( boolean hasFocus) { |
super .onWindowFocusChanged (hasFocus); |
mGLThread.onWindowFocusChanged (hasFocus); |
} |
public void queueEvent (Runnable r) { |
mGLThread.queueEvent (r); |
} |
@Override |
protected void onDetachedFromWindow() { |
super .onDetachedFromWindow(); |
mGLThread.requestExitAndWait(); |
} |
public interface GLWrapper { |
GL wrap (GL gl); |
} |
public interface Renderer { |
int [] getConfigSpec(); |
void surfaceCreated (GL10 gl); |
void sizeChanged (GL10 gl, int width, int height); |
void drawFrame (GL10 gl); |
} |
private class EglHelper { |
EGL10 mEgl; |
EGLDisplay mEglDisplay; |
EGLSurface mEglSurface; |
EGLConfig mEglConfig; |
EGLContext mEglContext; |
public EglHelper() { |
} |
public void start ( int [] configSpec) { |
mEgl = (EGL10) EGLContext.getEGL(); |
mEglDisplay = mEgl.eglGetDisplay (EGL10.EGL_DEFAULT_DISPLAY); |
int [] version = new int [ 2 ]; |
mEgl.eglInitialize (mEglDisplay, version); |
EGLConfig[] configs = new EGLConfig[ 1 ]; |
int [] num_config = new int [ 1 ]; |
mEgl.eglChooseConfig (mEglDisplay, configSpec, configs, 1 , |
num_config); |
mEglConfig = configs[ 0 ]; |
mEglContext = mEgl.eglCreateContext (mEglDisplay, mEglConfig, |
EGL10.EGL_NO_CONTEXT, null ); |
mEglSurface = null ; |
} |
public GL createSurface (SurfaceHolder holder) { |
if (mEglSurface != null ) { |
mEgl.eglMakeCurrent (mEglDisplay, EGL10.EGL_NO_SURFACE, |
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); |
mEgl.eglDestroySurface (mEglDisplay, mEglSurface); |
} |
mEglSurface = mEgl.eglCreateWindowSurface (mEglDisplay, |
mEglConfig, holder, null ); |
mEgl.eglMakeCurrent (mEglDisplay, mEglSurface, mEglSurface, |
mEglContext); |
GL gl = mEglContext.getGL(); |
if (mGLWrapper != null ) { |
gl = mGLWrapper.wrap (gl); |
} |
return gl; |
} |
public boolean swap() { |
mEgl.eglSwapBuffers (mEglDisplay, mEglSurface); |
return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST; |
} |
public void finish() { |
if (mEglSurface != null ) { |
mEgl.eglMakeCurrent (mEglDisplay, EGL10.EGL_NO_SURFACE, |
EGL10.EGL_NO_SURFACE, |
EGL10.EGL_NO_CONTEXT); |
mEgl.eglDestroySurface (mEglDisplay, mEglSurface); |
mEglSurface = null ; |
} |
if (mEglContext != null ) { |
mEgl.eglDestroyContext (mEglDisplay, mEglContext); |
mEglContext = null ; |
} |
if (mEglDisplay != null ) { |
mEgl.eglTerminate (mEglDisplay); |
mEglDisplay = null ; |
} |
} |
} |
class GLThread extends Thread { |
private boolean mDone; |
private boolean mPaused; |
private boolean mHasFocus; |
private boolean mHasSurface; |
private boolean mContextLost; |
private int mWidth; |
private int mHeight; |
private Renderer mRenderer; |
private ArrayList<Runnable> |
mEventQueue = new ArrayList<Runnable>(); |
private EglHelper mEglHelper; |
GLThread (Renderer renderer) { |
super (); |
mDone = false ; |
mWidth = 0 ; |
mHeight = 0 ; |
mRenderer = renderer; |
setName ( "GLThread" ); |
} |
@Override |
public void run() { |
try { |
try { |
sEglSemaphore.acquire(); |
} catch (InterruptedException e) { |
return ; |
} |
guardedRun(); |
} catch (InterruptedException e) { |
} finally { |
sEglSemaphore.release(); |
} |
} |
private void guardedRun() throws InterruptedException { |
mEglHelper = new EglHelper(); |
int [] configSpec = mRenderer.getConfigSpec(); |
mEglHelper.start (configSpec); |
GL10 gl = null ; |
boolean tellRendererSurfaceCreated = true ; |
boolean tellRendererSurfaceChanged = true ; |
while (!mDone) { |
int w, h; |
boolean changed; |
boolean needStart = false ; |
synchronized ( this ) { |
Runnable r; |
while ( (r = getEvent() ) != null ) { |
r.run(); |
} |
if (mPaused) { |
mEglHelper.finish(); |
needStart = true ; |
} |
if (needToWait() ) { |
while (needToWait() ) { |
wait(); |
} |
} |
if (mDone) { |
break ; |
} |
changed = mSizeChanged; |
w = mWidth; |
h = mHeight; |
mSizeChanged = false ; |
} |
if (needStart) { |
mEglHelper.start (configSpec); |
tellRendererSurfaceCreated = true ; |
changed = true ; |
} |
if (changed) { |
gl = (GL10) mEglHelper.createSurface (mHolder); |
tellRendererSurfaceChanged = true ; |
} |
if (tellRendererSurfaceCreated) { |
mRenderer.surfaceCreated (gl); |
tellRendererSurfaceCreated = false ; |
} |
if (tellRendererSurfaceChanged) { |
mRenderer.sizeChanged (gl, w, h); |
tellRendererSurfaceChanged = false ; |
} |
if ( (w > 0 ) && (h > 0 ) ) { |
mRenderer.drawFrame (gl); |
mEglHelper.swap(); |
} |
} |
mEglHelper.finish(); |
} |
private boolean needToWait() { |
return (mPaused || (! mHasFocus) || (! mHasSurface) || mContextLost) |
&& (! mDone); |
} |
public void surfaceCreated() { |
synchronized ( this ) { |
mHasSurface = true ; |
mContextLost = false ; |
notify(); |
} |
} |
public void surfaceDestroyed() { |
synchronized ( this ) { |
mHasSurface = false ; |
notify(); |
} |
} |
public void onPause() { |
synchronized ( this ) { |
mPaused = true ; |
} |
} |
public void onResume() { |
synchronized ( this ) { |
mPaused = false ; |
notify(); |
} |
} |
public void onWindowFocusChanged ( boolean hasFocus) { |
synchronized ( this ) { |
mHasFocus = hasFocus; |
if (mHasFocus == true ) { |
notify(); |
} |
} |
} |
public void onWindowResize ( int w, int h) { |
synchronized ( this ) { |
mWidth = w; |
mHeight = h; |
mSizeChanged = true ; |
} |
} |
public void requestExitAndWait() { |
synchronized ( this ) { |
mDone = true ; |
notify(); |
} |
try { |
join(); |
} catch (InterruptedException ex) { |
Thread.currentThread().interrupt(); |
} |
} |
public void queueEvent (Runnable r) { |
synchronized ( this ) { |
mEventQueue.add (r); |
} |
} |
private Runnable getEvent() { |
synchronized ( this ) { |
if (mEventQueue.size() > 0 ) { |
return mEventQueue.remove ( 0 ); |
} |
} |
return null ; |
} |
} |
} |
初级程序员
by: Andy_wang 发表于:2013-04-03 15:48:57 顶(0) | 踩(0) 回复
截图看看运行效果啊!
回复评论