Android(安卓)GLSurfaceView详解
16lz
2021-01-26
学习在Android中使用OpenGL ES,就不得不提到一个控件:GLSurfaceView
GLSurfaceView从Android 1.5(API level 3)开始加入,继承自SurfaceView,实现了SurfaceHolder.Callback2接口,拥有SurfaceView的全部特性,也有view所有的功能和属性,特别是处理事件的能力,它主要是在SurfaceView的基础上它加入了EGL的管理,并自带了一个GLThread绘制线程(EGLContext创建GL环境所在线程即为GL线程),绘制的工作直接通过OpenGL在绘制线程进行,不会阻塞主线程,绘制的结果输出到SurfaceView所提供的Surface上,这使得GLSurfaceView也拥有了OpenGlES所提供的图形处理能力,通过它定义的Render接口,使更改具体的Render的行为非常灵活性,只需要将实现了渲染函数的Renderer的实现类设置给GLSurfaceView即可。
GLSurfaceView提供了下列特性: 1> 提供并且管理一个独立的Surface。 2> 提供并且管理一个EGL display,它能让opengl把内容渲染到上述的Surface上。 3> 支持用户自定义渲染器(Render),通过setRenderer设置一个自定义的Renderer。 4> 让渲染器在独立的GLThread线程里运作,和UI线程分离。 5> 支持按需渲染(on-demand)和连续渲染(continuous)两种模式。 6> GPU加速:GLSurfaceView的效率是SurfaceView的30倍以上,SurfaceView使用画布进行绘制,GLSurfaceView利用GPU加速提高了绘制效率。 7> View的绘制onDraw(Canvas canvas)使用Skia渲染引擎渲染,而GLSurfaceView的渲染器Renderer的onDrawFrame(GL10 gl)使用opengl绘制引擎进行渲染。
在Activity中实例化,如下: @Override protected void onCreate (Bundle savedInstanceState){ GLSurfaceView glv = (GLSurfaceView)findViewById(R.id.glv_main); }
第三步:设置Renderer 渲染是OpenGLES的核心工作,setRenderer可以将用户自定义的一个 Renderer 加入实际的渲染流程中。 public class GLRender implements GLSurfaceView.Renderer{
//控制旋转的角度 private float rotate;
@Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { //关闭抗抖动 gl.glDisable(GL10.GL_DITHER); //设置系统对透视进行修正 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); gl .glClearColor ( 0 , 0 , 0 , 0 ) ; //设置阴影平滑模式 gl.glShadeModel(GL10.GL_SMOOTH); //启动深度测试 gl.glEnable(GL10.GL_DEPTH_TEST); //设置深度测试的类型 gl.glDepthFunc(GL10.GL_LEQUAL);
}
@Override public void onSurfaceChanged(GL10 gl, int width, int height) { //设置3D视窗的大小及位置 gl .glViewport ( 0 , 0 , width, height) ; //将当前矩阵模式设为投影矩形 gl.glMatrixMode(GL10.GL_PROJECTION); //初始化单位矩阵 gl.glLoadIdentity(); //计算透视窗口的宽度高度比 float ratio = (float) width / height; //调用此方法设置透视窗口的空间大小 gl .glFrustumf (-ratio, ratio, - 1 , 1 , 1 , 10 ) ; }
@Override public void onDrawFrame(GL10 gl) { //清除屏幕缓存和深度缓存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //启用顶点坐标数据 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); //启用顶点颜色数据 gl.glEnableClientState(GL10.GL_COLOR_ARRAY); //设置当前矩阵堆栈为模型堆栈 gl.glMatrixMode(GL10.GL_MODELVIEW); //------绘制第一个图形----- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl.glTranslatef(0.95f, -0.8f, -1.5f); //1⃣ //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (PointData .triangleData )) ; //设置顶点颜色数据 gl .glColorPointer ( 4 , GL10 .GL _FIXED, 0 , PointData .intBufferUtil (PointData .triangleColor )) ; //根据顶点数据绘制平面图形 gl .glDrawArrays (GL10 .GL _TRIANGLES, 0 , 3 ) ;
//-----绘制第二个图形----- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl .glTranslatef ( 0.95 f, 0.8 f, - 1.5 f) ; //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (PointData .rectData )) ; //设置顶点颜色数据 gl .glColorPointer ( 4 , GL10 .GL _FIXED, 0 , PointData .intBufferUtil (PointData .rectColor )) ; //更具顶点数据绘制平面图形 gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP, 0 , 4 ) ;
//-----绘制第三个图形---- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl .glTranslatef (- 0.95 f, 0.8 f, - 1.5 f) ; //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (PointData .rectData 2)) ; //根据顶点数据绘制平面图形 gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP, 0 , 4 ) ;
//-----绘制第四个图形----- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl.glTranslatef(-0.95f, -0.8f, -1.5f); //设置使用纯色填充 **需要注意: 使用纯色填充需要禁用顶点颜色数组 gl .glColor 4f( 1.0 f, 0.2 f, 0.2 f, 0.0 f) ; gl.glDisableClientState(GL10.GL_COLOR_ARRAY); //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (PointData .pentacle )) ; //根据顶点数据绘制图形 gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP, 0 , 5 ) ;
//----绘制第五个图形--- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl .glTranslatef ( 0 f, 0 f, - 1.5 f) ; gl .glRotatef (rotate, 0 f, 0.2 f, 0 f) ; //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (TDPointData .taperVertices )) ; //启用顶点颜色组 gl.glEnableClientState(GL10.GL_COLOR_ARRAY); //设置顶点颜色数据 gl .glColorPointer ( 4 , GL10 .GL _FIXED, 0 , PointData .intBufferUtil (TDPointData .taperColors )) ; //按taperFacetsBuffer指定的面绘制三角形 ByteBuffer byteBuffer = PointData.byteBufferUtil(TDPointData.taperFacets); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, byteBuffer.remaining(), GL10.GL_UNSIGNED_BYTE, byteBuffer);
//绘制结束 gl.glFinish(); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); //旋转角度+1 rotate += 1 ; } }
@Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_glsurface); glv = (GLSurfaceView)findViewById(R.id.glv_opengl); GLRender render = new GLRender(); glv.setRenderer(render); }
第六部:事件处理 为了处理事件,一般都是继承GLSurfaceView类并重载它的事件方法,但是由于GLSurfaceView是多线程的,渲染器在独立的渲染线程里,你应该使用Java的跨线程机制跟渲染器通讯,GLSurfaceView提供的queueEvent(Runnable)方法就是一种相对简单的操作,queueEvent()方法被安全地用于在UI线程和渲染线程之间进行交流通信: public void queueEvent(Runnable r) { mGLThread.queueEvent(r); }
这里直接调用 GLThread的 queueEvent(Runnable r)方法 给 GLThread的 mEventQueue 队列中添加 Runnable public void queueEvent(Runnable r) { synchronized(sGLThreadManager) { mEventQueue.add(r); sGLThreadManager.notifyAll(); } }
在GLThread的guardenRun()方法中有如下代码:
GLSurfaceView源码分析 GLSurfaceView中对于GL环境的操作,除queueEvent是将事件放入队列中然后到GL线程中执行外, 其他方法基本都是在主线程中修改某个状态值(某个属性属性),然后调用 取消GL线程的等待, 在GL线程中根据属性的状态值作不同的操作,并在操作后反馈给主线程,当然有的方法也不需要反馈。 相关类图如下,GLSurfaceView中的EglHelper和GLThread分别实现了上面提到的管理EGL环境和渲染线程的工作,GLSurfaceView的使用者需要实现Renderer接口。
渲染的整体步骤如下:
public class GLSurfaceView extends SurfaceView implements SurfaceHolder . Callback2 {
public final static int RENDERMODE_WHEN_DIRTY = 0 ;//按需渲染模式 public final static int RENDERMODE_CONTINUOUSLY = 1 ;//连续渲染模式
private static final GLThreadManager sGLThreadManager = new GLThreadManager() ;
private final WeakReference mThisWeakRef = new WeakReference( this ) ; private GLThread mGLThread ; private Renderer mRenderer ; private boolean mDetached ; private EGLConfigChooser mEGLConfigChooser ; private EGLContextFactory mEGLContextFactory ; private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory ; private int mDebugFlags ; private int mEGLContextClientVersion ; private boolean mPreserveEGLContextOnPause ;
public GLSurfaceView (Context context) { super (context); init(); }
public GLSurfaceView (Context context, AttributeSet attrs) { super (context, attrs); init(); }
//调试用的 public void setDebugFlags ( int debugFlags); public int getDebugFlags ();
//设置暂停的时候是否保持EglContext public void setPreserveEGLContextOnPause ( boolean preserveOnPause); public boolean getPreserveEGLContextOnPause ();
//设置渲染器,这个非常重要,渲染工作就依靠渲染器了 //调用此方法会开启一个新的线程,即GL线程 public void setRenderer (Renderer renderer) { checkRenderThreadState();//检查渲染线程是否已经创建了,如果已经创建了就抛出异常 if (mEGLConfigChooser == null ) { mEGLConfigChooser = new SimpleEGLConfigChooser( true );//默认的 } if (mEGLContextFactory == null ) { mEGLContextFactory = new DefaultContextFactory();// } if (mEGLWindowSurfaceFactory == null ) { mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();// } mRenderer = renderer; mGLThread = new GLThread(mThisWeakRef); mGLThread.start(); }
//设置EGLContext工厂,不设置就用默认的 public void setEGLContextFactory (EGLContextFactory factory){ checkRenderThreadState() ; mEGLContextFactory = factory ; }
//设置EGLSurface工厂,不设置就用默认的 public void setEGLWindowSurfaceFactory (EGLWindowSurfaceFactory factory){ checkRenderThreadState() ; mEGLWindowSurfaceFactory = factory ; } //设置EglConfig,一般颜色深度等等,利用此方法设置。不设置就用默认的 public void setEGLConfigChooser (EGLConfigChooser configChooser){ checkRenderThreadState() ; mEGLConfigChooser = configChooser ; }
//内部调用setEGLConfigChooser public void setEGLConfigChooser ( boolean needDepth){ setEGLConfigChooser( new SimpleEGLConfigChooser(needDepth)) ; }
//内部调用setEGLConfigChooser public void setEGLConfigChooser ( int redSize, int greenSize, int blueSize, int alphaSize, int depthSize, int stencilSize){ setEGLConfigChooser( new ComponentSizeChooser(redSize , greenSize , blueSize , alphaSize , depthSize , stencilSize)) ; }
//设置EGLContextVersion,比如2,即OpenGLES2.0 public void setEGLContextClientVersion ( int version){ checkRenderThreadState() ; mEGLContextClientVersion = version ; }
//设置渲染方式,有RENDERMODE_CONTINUOUSLY表示不断渲染 //以及RENDERMODE_WHEN_DIRTY表示在需要的时候才会渲染 //渲染的时候调用requestRender必须在setRenderer后 public void setRenderMode ( int renderMode){ mGLThread .setRenderMode(renderMode) ; }
public int getRenderMode (){ return mGLThread .getRenderMode() ; }
//主动请求渲染 public void requestRender (){ mGLThread .requestRender() ; }
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) ; }
@Override public void surfaceRedrawNeeded (SurfaceHolder holder) { if (mGLThread != null ) { mGLThread.requestRenderAndWait(); } }
//生命周期,一般在Activity、Fragment的onPause中调用 public void onPause (){ mGLThread .onPause() ; }
//生命周期,一般在Activity、Fragment的onResume中调用 public void onResume (){ mGLThread .onResume() ; }
//向GL线程发送一个任务 public void queueEvent (Runnable r){ mGLThread .queueEvent(r) ; }
//附加到Window上时被调用,外部不可调用 protected void onAttachedToWindow (){ super .onAttachedToWindow() ; if ( mDetached && ( mRenderer != null )) { int renderMode = RENDERMODE_CONTINUOUSLY ; if ( mGLThread != null ) { renderMode = mGLThread .getRenderMode() ; } mGLThread = new GLThread( mThisWeakRef ) ; if (renderMode != RENDERMODE_CONTINUOUSLY ) { mGLThread .setRenderMode(renderMode) ; } mGLThread .start() ; } mDetached = false; }
//从Window上被移除时调用,外部不可调用 protected void onDetachedFromWindow (){ if ( mGLThread != null ) { mGLThread .requestExitAndWait() ; } mDetached = true; super .onDetachedFromWindow() ; }
//渲染器接口 public interface Renderer {
//Surface被创建时被调用,通常在此进行渲染的初始化 void onSurfaceCreated(GL10 gl, EGLConfig config);
//Surface大小被改变时被调用 void onSurfaceChanged(GL10 gl, int width, int height);
//执行渲染时被调用,以完成用户渲染工作 void onDrawFrame(GL10 gl);
}
//非常重要的一个EGL帮助类,GL环境的建立依靠此类 private static class EglHelper { public EglHelper (WeakReference glSurfaceViewWeakRef) { mGLSurfaceViewWeakRef = glSurfaceViewWeakRef; }
//EGL的初始化,可以参考此方法 public void start () { /* * Get an EGL instance */ mEgl = (EGL10) EGLContext.getEGL();
/* * Get to the default display. */ mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { throw new RuntimeException( "eglGetDisplay failed" ); }
/* * We can now initialize EGL for that display */ int [] version = new int [ 2 ]; if (!mEgl.eglInitialize(mEglDisplay, version)) { throw new RuntimeException( "eglInitialize failed" ); } GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view == null ) { mEglConfig = null ; mEglContext = null ; } else { mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
/* * Create an EGL context. We want to do this as rarely as we can, because an * EGL context is a somewhat heavy object. */ mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); } if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { mEglContext = null ; throwEglException("createContext"); } if (LOG_EGL) { Log.w( "EglHelper" , "createContext " + mEglContext + " tid=" + Thread.currentThread().getId()); }
mEglSurface = null ; }
//创建EGLSurface,使GL的渲染,能够渲染到用户指定的Surface //默认的Surface就是SurfaceHolder的Surface public boolean createSurface () { /* * Check preconditions. */ if (mEgl == null ) { throw new RuntimeException( "egl not initialized" ); } if (mEglDisplay == null ) { throw new RuntimeException( "eglDisplay not initialized" ); } if (mEglConfig == null ) { throw new RuntimeException( "mEglConfig not initialized" ); }
/* * The window size has changed, so we need to create a new * surface. */ destroySurfaceImp();
/* * Create an EGL surface we can render into. */ GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null ) { mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, view.getHolder()); } else { mEglSurface = null ; }
if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { int error = mEgl.eglGetError(); if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { Log.e( "EglHelper" , "createWindowSurface returned EGL_BAD_NATIVE_WINDOW." ); } return false ; }
/* * Before we can issue GL commands, we need to make sure * the context is current and bound to a surface. */ if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { /* * Could not make the context current, probably because the underlying * SurfaceView surface has been destroyed. */ logEglErrorAsWarning( "EGLHelper" , "eglMakeCurrent" , mEgl.eglGetError()); return false ; }
return true ; }
//通过EGL得到GL,然后用户设置了Wrapper的话会给得到的GL做个包装 //同时也会解析一下用户的Debug意图,看看要不要debug GL createGL(){
GL gl = mEglContext.getGL(); GLSurfaceView view = mGLSurfaceViewWeakRef .get() ; if (view != null ) { if (view.mGLWrapper != null ) { gl = view.mGLWrapper.wrap(gl) ; }
if ((view.mDebugFlags & ( DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS )) != 0 ) { int configFlags = 0 ; Writer log = null; if ((view.mDebugFlags & DEBUG_CHECK_GL_ERROR ) != 0 ) { configFlags |= GLDebugHelper. CONFIG_CHECK_GL_ERROR ; } if ((view.mDebugFlags & DEBUG_LOG_GL_CALLS ) != 0 ) { log = new LogWriter() ; } gl = GLDebugHelper. wrap (gl , configFlags , log) ; } } return gl ; }
//绘制完成之后,调用此方法,将绘制的内容输出到前台,让用户可以看到 public int swap (){ if (! mEgl .eglSwapBuffers( mEglDisplay , mEglSurface )) { return mEgl .eglGetError() ; } return EGL10. EGL_SUCCESS ; }
//销毁Surface的方法,具体实现在destroySurfaceImp方法中 public void destroySurface() { destroySurfaceImp() ; }
private void destroySurfaceImp () { if ( mEglSurface != null && mEglSurface != EGL10. EGL_NO_SURFACE ) { mEgl .eglMakeCurrent( mEglDisplay , EGL10. EGL_NO_SURFACE , EGL10. EGL_NO_SURFACE , EGL10. EGL_NO_CONTEXT ) ; GLSurfaceView view = mGLSurfaceViewWeakRef .get() ; if (view != null ) { view.mEGLWindowSurfaceFactory.destroySurface( mEgl , mEglDisplay , mEglSurface ) ; } mEglSurface = null; } } public void finish () { if ( mEglContext != null ) { GLSurfaceView view = mGLSurfaceViewWeakRef .get() ; if (view != null ) { view.mEGLContextFactory.destroyContext( mEgl , mEglDisplay , mEglContext ) ; } mEglContext = null; } if ( mEglDisplay != null ) { mEgl .eglTerminate( mEglDisplay ) ; mEglDisplay = null; } } } ---------------------------------------------------------------------------------------------- //GL线程,此类中存在的方法在GLSurfaceView中都有同名的, 都是提供给GLSurfaceView作为真正的实现调用 static class GLThread extends Thread {
GLSurfaceView中对于GL环境的操作,除queueEvent是将事件放入队列中然后到GL线程中执行外, 其他方法基本都是在主线程中修改某个状态值(下面的某个属性属性),然后调用取消GL线程的等待, 在GL线程中根据属性的状态值作不同的操作,并在操作后反馈给主线程,当然有的方法也不需要反馈。 private boolean mShouldExit; private boolean mExited ; private boolean mRequestPaused ; private boolean mPaused ; private boolean mHasSurface ; private boolean mSurfaceIsBad ; private boolean mWaitingForSurface ; private boolean mHaveEglContext ; private boolean mHaveEglSurface ; private boolean mFinishedCreatingEglSurface ; private boolean mShouldReleaseEglContext ; private int mWidth ; private int mHeight ; private int mRenderMode ; private boolean mRequestRender ; private boolean mWantRenderNotification ; private boolean mRenderComplete ; private ArrayList mEventQueue = new ArrayList() ; private boolean mSizeChanged = true;
// End of member variables protected by the sGLThreadManager monitor. private EglHelper mEglHelper ;
private WeakReference mGLSurfaceViewWeakRef ;
GLThread (WeakReference glSurfaceViewWeakRef) { super () ; mWidth = 0 ; mHeight = 0 ; mRequestRender = true;//开始需要刷新一次 mRenderMode = RENDERMODE_CONTINUOUSLY ;//默认的渲染模式 mWantRenderNotification = false; mGLSurfaceViewWeakRef = glSurfaceViewWeakRef ; }
@Override public void run () { setName( "GLThread " + getId()) ; try { guardedRun() ;//处理所有渲染逻辑
} catch (InterruptedException e) { } finally { sGLThreadManager .threadExiting( this ) ; } }
//销毁EglSurface private void stopEglSurfaceLocked (){ if ( mHaveEglSurface ) { mHaveEglSurface = false; mEglHelper .destroySurface() ; } }
//销毁EglContext private void stopEglContextLocked (){ if ( mHaveEglContext ) { mEglHelper .finish() ; mHaveEglContext = false; sGLThreadManager .releaseEglContextLocked( this ) ; } }
// GL线程 都在这个方法里面,这个方法比较复杂 第一步:判断事件队列是否为空,如果有事件需要处理,则直接跳出内循环去处理事件,否则依然在内循环运行 第二步:1.判断是否需要释放EGLSurface, 2.判断是否丢失了Surface,mHasSurface表示当前有没有可用的Surface,mWaitingForSurface表示是否在申请Surface的过程中, 3.是否需要放弃EGLContext 第三步:经过以上的判断之后,程序进入图形渲染前的准备工作,也就是readyToDraw之间的代码 第四步:一旦程序执行到这里也就是跳出了内循环,有两种可能,第一是EventQueue中有需要处理的事件,第二是需要执行渲染工作 private void guardedRun () throws InterruptedException { mEglHelper = new EglHelper(mGLSurfaceViewWeakRef);//初始化 mHaveEglContext = false ; mHaveEglSurface = false ; mWantRenderNotification = false ;
try { GL10 gl = null ; boolean createEglContext = false ; boolean createEglSurface = false ; boolean createGlInterface = false ; boolean lostEglContext = false ; boolean sizeChanged = false ; boolean wantRenderNotification = false ; boolean doRenderNotification = false ; boolean askedToReleaseEglContext = false ; int w = 0 ; int h = 0 ; Runnable event = null ;
while ( true ) { synchronized (sGLThreadManager) { while ( true ) {//死循环,除非主动跳出 //外部请求退出GL线程 if (mShouldExit) { return ; }
/*外部请求在GL线程中处理的事件没有处理完时,就优先处理这些事件*/ if (! mEventQueue.isEmpty()) { event = mEventQueue.remove( 0 ); break ; }
//暂停和恢复状态变化时,onResume和onPause状态变化 boolean pausing = false ; if (mPaused != mRequestPaused) { pausing = mRequestPaused; mPaused = mRequestPaused; /*GLSurfaceView的onPause和onResume都会用wait方法等待GL线程的响应,这时候主线程阻塞。 此处调用notifyAll通知onPause和onResume,放弃主线程的阻塞。 GLSurfaceView中其他很多方法也存在wait方法,基本与此类似 */ sGLThreadManager.notifyAll(); }
// 需要释放EglContext时候执行的工作 if (mShouldReleaseEglContext) { stopEglSurfaceLocked(); stopEglContextLocked(); mShouldReleaseEglContext = false ; askedToReleaseEglContext = true ; }
// EglContext丢失时,销毁EglSurface和EglContext if (lostEglContext) { stopEglSurfaceLocked(); stopEglContextLocked(); lostEglContext = false ; }
// 如果 acitivity 已经暂停, 接收了暂停信号,而且当前EglSurface存在时,销毁EglSurface if (pausing && mHaveEglSurface) { stopEglSurfaceLocked(); }
/*接收了暂停信号,而且当前EglContext存在时,根据用户设置,来决定是否销毁EglContext*/ if (pausing && mHaveEglContext) { GLSurfaceView view = mGLSurfaceViewWeakRef.get(); boolean preserveEglContextOnPause = view == null ? false : view.mPreserveEGLContextOnPause; if (!preserveEglContextOnPause) { stopEglContextLocked(); } }
/*Surface不存在而且当前并没有在等待Surface*/ if ((! mHasSurface) && (! mWaitingForSurface)) { if (mHaveEglSurface) { stopEglSurfaceLocked(); } mWaitingForSurface = true ; mSurfaceIsBad = false ; sGLThreadManager.notifyAll(); }
// Surface存在,而且在等待Surface if (mHasSurface && mWaitingForSurface) { mWaitingForSurface = false ; sGLThreadManager.notifyAll(); }
if (doRenderNotification) { mWantRenderNotification = false ; doRenderNotification = false ; mRenderComplete = true ; sGLThreadManager.notifyAll(); }
// 判断当前环境准备好了渲染执行,否则进入下一轮等待及判断 判断两个关键因素:EGLContext和EGLSurface是否存在并有效,如果没有EGLContext,就需要获取一个, 如果当前有EGLSurface但尺寸发生了变化,那么就需要销毁他并重新申请Surface。 可以渲染图形的条件是: 1.程序当前不处于pause状态, 2.已经成功获得Surface, 3.有合适的尺寸, 4.处于自动持续渲染状态或用户发起了渲染请求 if (readyToDraw()) {
// 没有EglContext就需要借助EglHelper来创建EglContext if (! mHaveEglContext) { if (askedToReleaseEglContext) { askedToReleaseEglContext = false ; } else { try { mEglHelper.start(); } catch (RuntimeException t) { sGLThreadManager.releaseEglContextLocked( this ); throw t; } mHaveEglContext = true ; createEglContext = true ;
sGLThreadManager.notifyAll(); } }
/*有了EglContext,但是没有EglSurface,就需要设置一些状态,以便后续操作*/ if (mHaveEglContext && !mHaveEglSurface) { mHaveEglSurface = true ; createEglSurface = true ; createGlInterface = true ; sizeChanged = true ; }
/*有eglSurface时,需要判断是否需要执行surface sizechange*/ if (mHaveEglSurface) { if (mSizeChanged) { sizeChanged = true ; w = mWidth; h = mHeight; mWantRenderNotification = true ; // Destroy and recreate the EGL surface. createEglSurface = true ;
mSizeChanged = false ; } mRequestRender = false ; sGLThreadManager.notifyAll(); if (mWantRenderNotification) { wantRenderNotification = true ; } //注意此处break,跳出等待的循环 break ; } }
// By design, this is the only place in a GLThread thread where we wait(). sGLThreadManager.wait(); } }
/*外部请求在GL线程中处理的事件没有处理完时,就优先处理这些事件*/ if (event != null ) { event.run(); event = null ; continue ; }
//后续就是根据上面的判断设置,来执行相应的操作 if (createEglSurface) {//EglSurface需要被创建 //创建EglSurface if (mEglHelper.createSurface()) { synchronized (sGLThreadManager) { mFinishedCreatingEglSurface = true ; sGLThreadManager.notifyAll(); } } else { synchronized (sGLThreadManager) { mFinishedCreatingEglSurface = true ; mSurfaceIsBad = true ; sGLThreadManager.notifyAll(); } continue ; } createEglSurface = false ; }
if (createGlInterface) { gl = (GL10) mEglHelper.createGL();
createGlInterface = false ; }
if (createEglContext) {
GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null ) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onSurfaceCreated" ); //调用GLSurfaceView设置的renderer的onSurfceCreated方法 view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } createEglContext = false ; }
//surface大小被改变 if (sizeChanged) { GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null ) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onSurfaceChanged" ); view.mRenderer.onSurfaceChanged(gl, w, h);//通知应用程序尺寸发生了变化 } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } sizeChanged = false ; }
//每帧绘制 { GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null ) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onDrawFrame" ); view.mRenderer.onDrawFrame(gl);//调用应用程序的Renderer渲染 } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } } //提交绘制结果,通过swap把渲染结果显示到屏幕上 int swapError = mEglHelper.swap(); switch (swapError) { case EGL10.EGL_SUCCESS: break ; case EGL11.EGL_CONTEXT_LOST: lostEglContext = true ; break ; default : EglHelper.logEglErrorAsWarning( "GLThread" , "eglSwapBuffers" , swapError);
synchronized (sGLThreadManager) { mSurfaceIsBad = true ; sGLThreadManager.notifyAll(); } break ; }
if (wantRenderNotification) { doRenderNotification = true ; wantRenderNotification = false ; } }
} finally { /* * clean-up everything... */ synchronized (sGLThreadManager) { stopEglSurfaceLocked(); stopEglContextLocked(); } }
}
public boolean ableToDraw () { return mHaveEglContext && mHaveEglSurface && readyToDraw(); }
private boolean readyToDraw () { return (!mPaused) && mHasSurface && (!mSurfaceIsBad) && (mWidth > 0 ) && (mHeight > 0 ) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)); }
//设置渲染方法,见GLSurfaceView的setRenderMode public void setRenderMode ( int renderMode){ if ( !(( RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY )) ) { throw new IllegalArgumentException( "renderMode" ) ; } synchronized ( sGLThreadManager ) { mRenderMode = renderMode ; sGLThreadManager .notifyAll() ; } }
public int getRenderMode (){ synchronized ( sGLThreadManager ) { return mRenderMode ; } }
//请求一次渲染 public void requestRender (){ synchronized ( sGLThreadManager ) { mRequestRender = true; sGLThreadManager .notifyAll() ; } }
//请求一次渲染,并等待渲染完成 public void requestRenderAndWait (){ synchronized ( sGLThreadManager ) { if (Thread. currentThread () == this ) { return; }
mWantRenderNotification = true; mRequestRender = true; mRenderComplete = false;
sGLThreadManager .notifyAll() ;
while (! mExited && ! mPaused && ! mRenderComplete && ableToDraw()) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } }
} } //创建Surface public void surfaceCreated (){ synchronized ( sGLThreadManager ) { mHasSurface = true; mFinishedCreatingEglSurface = false; sGLThreadManager .notifyAll() ; while ( mWaitingForSurface && ! mFinishedCreatingEglSurface && ! mExited ) { try { sGLThreadManager .wait() ; } catch (InterruptedException e) { Thread. currentThread ().interrupt() ; } } } }
//销毁Surface public void surfaceDestroyed (){ synchronized ( sGLThreadManager ) { mHasSurface = false; sGLThreadManager .notifyAll() ; while ((! mWaitingForSurface ) && (! mExited )) { try { sGLThreadManager .wait() ; } catch (InterruptedException e) { Thread. currentThread ().interrupt() ; } } } }
public void onPause (){ synchronized ( sGLThreadManager ) { mRequestPaused = true; sGLThreadManager .notifyAll() ; while ((! mExited ) && (! mPaused )) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } } } } public void onResume (){ synchronized ( sGLThreadManager ) { mRequestPaused = false; mRequestRender = true; mRenderComplete = false; sGLThreadManager .notifyAll() ; while ((! mExited ) && mPaused && (! mRenderComplete )) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } } } }
//Surface的大小被改变时调用 public void onWindowResize ( int w, int h){ synchronized ( sGLThreadManager ) { mWidth = w ; mHeight = h ; mSizeChanged = true; mRequestRender = true; mRenderComplete = false;
if (Thread. currentThread () == this ) { return; }
sGLThreadManager .notifyAll() ;
while (! mExited && ! mPaused && ! mRenderComplete && ableToDraw()) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } } } }
//请求退出渲染线程,并等待退出 public void requestExitAndWait (){ synchronized ( sGLThreadManager ) { mShouldExit = true; sGLThreadManager .notifyAll() ; while (! mExited ) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } } } }
//请求回收EglContext public void requestReleaseEglContextLocked (){ mShouldReleaseEglContext = true; sGLThreadManager .notifyAll() ; }
//向GL线程发送一个任务 public void queueEvent (Runnable r){ if (r == null ) { throw new IllegalArgumentException( "r must not be null" ) ; } synchronized ( sGLThreadManager ) { mEventQueue .add(r) ; sGLThreadManager .notifyAll() ; } }
}
//很多方法都会调用此方法,会检查mGLThread不为null, 即保证调用此方法的方法,必须在setRenderer之前调用 private void checkRenderThreadState (){ if ( mGLThread != null ) { throw new IllegalStateException( "setRenderer has already been called for this instance." ) ; } }
//主要就是用来做同步用的,利用Object的wait和notifyAll private static class GLThreadManager {
public synchronized void threadExiting(GLThread thread) { thread. mExited = true; notifyAll() ; }
public void releaseEglContextLocked(GLThread thread) { notifyAll() ; } }
}
EGLHelper readyToDraw后调用了 EGLHelper. start方法初始化,然后跳出readyToDraw后调用了 EGLHelper. createSurface方法创建一个 EglSurface, 最后绘制完成以后 通过 EGLHelper. swap把渲染结果显示到屏幕上。
第一步: EGLHelper. start()方法初始化EGLHelper的内容 public void start() { mEgl = (EGL10) EGLContext.getEGL();//获取一个EGL实例 //获取一个EGLDisplay mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
//初始化EGL并返回版本号 if(!mEgl.eglInitialize(mEglDisplay, version)) { } GLSurfaceView view = mGLSurfaceViewWeakRef.get(); //选取一个配置 mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); //创建EGLContext mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); mEglSurface = null; }
第二步:如果需要创建 EglSurface,调用 mEglHelper.createSurface()方法 public boolean createSurface() { if (LOG_EGL) { Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId()); } /* * Check preconditions. */ if (mEgl == null) { throw new RuntimeException("egl not initialized"); } if (mEglDisplay == null) { throw new RuntimeException("eglDisplay not initialized"); } if (mEglConfig == null) { throw new RuntimeException("mEglConfig not initialized"); } GLSurfaceView view = mGLSurfaceViewWeakRef.get(); mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, view.getHolder());
return true; }
private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, Object nativeWindow) { EGLSurface result = null; result = egl.eglCreateWindowSurface(display, config, nativeWindow, null); return result; }
}
第三步:提交绘制结果,通过mEglHelper.swap()把渲染结果显示到屏幕上 public int swap() { if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { return mEgl.eglGetError(); } return EGL10.EGL_SUCCESS; }
总结GLSurfaceView使用EGL的流程如下: 1.生成一个EGL实例 mEgl = (EGL10) EGLContext.getEGL(); 2.获取一个EGL Display mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 3.初始化EGL并返回版本号 if(!mEgl.eglInitialize(mEglDisplay, version)) {} 4.选取一个配置 mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); 5.创建一个EGLContext mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); 6.创建EGLSurface egl.eglCreateWindowSurface(display, config, nativeWindow, null); 7.通过swap将渲染内容显示到屏幕 mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)
GLSurfaceView从Android 1.5(API level 3)开始加入,继承自SurfaceView,实现了SurfaceHolder.Callback2接口,拥有SurfaceView的全部特性,也有view所有的功能和属性,特别是处理事件的能力,它主要是在SurfaceView的基础上它加入了EGL的管理,并自带了一个GLThread绘制线程(EGLContext创建GL环境所在线程即为GL线程),绘制的工作直接通过OpenGL在绘制线程进行,不会阻塞主线程,绘制的结果输出到SurfaceView所提供的Surface上,这使得GLSurfaceView也拥有了OpenGlES所提供的图形处理能力,通过它定义的Render接口,使更改具体的Render的行为非常灵活性,只需要将实现了渲染函数的Renderer的实现类设置给GLSurfaceView即可。
GLSurfaceView提供了下列特性: 1> 提供并且管理一个独立的Surface。 2> 提供并且管理一个EGL display,它能让opengl把内容渲染到上述的Surface上。 3> 支持用户自定义渲染器(Render),通过setRenderer设置一个自定义的Renderer。 4> 让渲染器在独立的GLThread线程里运作,和UI线程分离。 5> 支持按需渲染(on-demand)和连续渲染(continuous)两种模式。 6> GPU加速:GLSurfaceView的效率是SurfaceView的30倍以上,SurfaceView使用画布进行绘制,GLSurfaceView利用GPU加速提高了绘制效率。 7> View的绘制onDraw(Canvas canvas)使用Skia渲染引擎渲染,而GLSurfaceView的渲染器Renderer的onDrawFrame(GL10 gl)使用opengl绘制引擎进行渲染。
2.GLSurfaceView的使用步骤
开发基于GLSurfaceView的程序,通常需要继承GLSurfaceView,并重载一些和用户输入事件有关的方法,如果你不需监听事件,也可以直接使用GLSurfaceView, 你可以使用set方法来修改默认的属性,例如setRenderer(Renderer)设置渲染器,主要的工作就是设置Renderer,其他过程,例如EGL的创建,Surface的分配以及OpenGLES的调用都被隐藏起来了,GLSurfaceView会启动一个工作线程来完成渲染,避免阻塞UI主线程,这个工作线程就是mGLThread,这个线程在应用程序setRederer的时候启动,然后不停地等待和处理事件,同时还负责开展Render工作。第一步:创建GLSurfaceView
GLSurfaceView也是View,可以通过布局文件的方式将它加入整棵view树中,或者在java代码中创建并且添加。 在布局中,摆布好GLSurfaceView的位置.如下: .opengl.GLSurfaceView android:id="@+id/glv_main" android:layout_width="match_parent" android:layout_height= "200dp" />在Activity中实例化,如下: @Override protected void onCreate (Bundle savedInstanceState){ GLSurfaceView glv = (GLSurfaceView)findViewById(R.id.glv_main); }
第二步:初始化OpenGLES环境
GLSurfaceView默认情况下已经初始化好了OpenGLES的运行环境,不需要做额外的工作就可以使用,当然也可以更改一些默认的设置。第三步:设置Renderer 渲染是OpenGLES的核心工作,setRenderer可以将用户自定义的一个 Renderer 加入实际的渲染流程中。 public class GLRender implements GLSurfaceView.Renderer{
//控制旋转的角度 private float rotate;
@Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { //关闭抗抖动 gl.glDisable(GL10.GL_DITHER); //设置系统对透视进行修正 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); gl .glClearColor ( 0 , 0 , 0 , 0 ) ; //设置阴影平滑模式 gl.glShadeModel(GL10.GL_SMOOTH); //启动深度测试 gl.glEnable(GL10.GL_DEPTH_TEST); //设置深度测试的类型 gl.glDepthFunc(GL10.GL_LEQUAL);
}
@Override public void onSurfaceChanged(GL10 gl, int width, int height) { //设置3D视窗的大小及位置 gl .glViewport ( 0 , 0 , width, height) ; //将当前矩阵模式设为投影矩形 gl.glMatrixMode(GL10.GL_PROJECTION); //初始化单位矩阵 gl.glLoadIdentity(); //计算透视窗口的宽度高度比 float ratio = (float) width / height; //调用此方法设置透视窗口的空间大小 gl .glFrustumf (-ratio, ratio, - 1 , 1 , 1 , 10 ) ; }
@Override public void onDrawFrame(GL10 gl) { //清除屏幕缓存和深度缓存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //启用顶点坐标数据 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); //启用顶点颜色数据 gl.glEnableClientState(GL10.GL_COLOR_ARRAY); //设置当前矩阵堆栈为模型堆栈 gl.glMatrixMode(GL10.GL_MODELVIEW); //------绘制第一个图形----- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl.glTranslatef(0.95f, -0.8f, -1.5f); //1⃣ //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (PointData .triangleData )) ; //设置顶点颜色数据 gl .glColorPointer ( 4 , GL10 .GL _FIXED, 0 , PointData .intBufferUtil (PointData .triangleColor )) ; //根据顶点数据绘制平面图形 gl .glDrawArrays (GL10 .GL _TRIANGLES, 0 , 3 ) ;
//-----绘制第二个图形----- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl .glTranslatef ( 0.95 f, 0.8 f, - 1.5 f) ; //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (PointData .rectData )) ; //设置顶点颜色数据 gl .glColorPointer ( 4 , GL10 .GL _FIXED, 0 , PointData .intBufferUtil (PointData .rectColor )) ; //更具顶点数据绘制平面图形 gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP, 0 , 4 ) ;
//-----绘制第三个图形---- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl .glTranslatef (- 0.95 f, 0.8 f, - 1.5 f) ; //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (PointData .rectData 2)) ; //根据顶点数据绘制平面图形 gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP, 0 , 4 ) ;
//-----绘制第四个图形----- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl.glTranslatef(-0.95f, -0.8f, -1.5f); //设置使用纯色填充 **需要注意: 使用纯色填充需要禁用顶点颜色数组 gl .glColor 4f( 1.0 f, 0.2 f, 0.2 f, 0.0 f) ; gl.glDisableClientState(GL10.GL_COLOR_ARRAY); //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (PointData .pentacle )) ; //根据顶点数据绘制图形 gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP, 0 , 5 ) ;
//----绘制第五个图形--- //重置当前的模型视图矩阵 gl.glLoadIdentity(); gl .glTranslatef ( 0 f, 0 f, - 1.5 f) ; gl .glRotatef (rotate, 0 f, 0.2 f, 0 f) ; //设置顶点位置数据 gl .glVertexPointer ( 3 , GL10 .GL _FLOAT, 0 , PointData .floatBufferUtil (TDPointData .taperVertices )) ; //启用顶点颜色组 gl.glEnableClientState(GL10.GL_COLOR_ARRAY); //设置顶点颜色数据 gl .glColorPointer ( 4 , GL10 .GL _FIXED, 0 , PointData .intBufferUtil (TDPointData .taperColors )) ; //按taperFacetsBuffer指定的面绘制三角形 ByteBuffer byteBuffer = PointData.byteBufferUtil(TDPointData.taperFacets); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, byteBuffer.remaining(), GL10.GL_UNSIGNED_BYTE, byteBuffer);
//绘制结束 gl.glFinish(); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); //旋转角度+1 rotate += 1 ; } }
@Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_glsurface); glv = (GLSurfaceView)findViewById(R.id.glv_opengl); GLRender render = new GLRender(); glv.setRenderer(render); }
第四步:设置RenderingMode
GLSurfaceView 在onAttachedToWindow后就启动了一个无线循环的 GLThread 线程, GLSurfaceView默认采用的是 RENDERMODE_CONTINUOUSLY 连续渲染的方式, 刷新的帧率是60FPS,16ms就重绘一次, 可以通过 mGLView.setRenderMode()更改其渲染方式为 RENDERMODE_WHEN_DIRTY,表示被动渲染,在 surfaceCreate的时候会绘制一次,之后 只有在调用requestRender或者onResume等方法 主动请求重绘 时才会进行渲染, 如果你的界面不需要频繁的刷新最好使用 RENDERMODE_WHEN_DIRTY ,这样可以降低CPU和GPU的活动 。第五步:状态处理
使用GLSurfaceView需要注意程序的生命周期, Activity及Fragment 会有暂停和恢复等状态,GLSurfaceView也需根据这些状态来做相应的处理, GLSurfaceView具有onResume和onPause两个同Activity及Fragment中的生命周期同名的方法,在Activity或者Fragment中的onResume和onPause方法中,需要主动调用GLSurfaceView的实例的这两个方法 ,这样能使OpenGLES的内部线程做出正确的判断,从而保证应用程序的稳定性。第六部:事件处理 为了处理事件,一般都是继承GLSurfaceView类并重载它的事件方法,但是由于GLSurfaceView是多线程的,渲染器在独立的渲染线程里,你应该使用Java的跨线程机制跟渲染器通讯,GLSurfaceView提供的queueEvent(Runnable)方法就是一种相对简单的操作,queueEvent()方法被安全地用于在UI线程和渲染线程之间进行交流通信: public void queueEvent(Runnable r) { mGLThread.queueEvent(r); }
这里直接调用 GLThread的 queueEvent(Runnable r)方法 给 GLThread的 mEventQueue 队列中添加 Runnable public void queueEvent(Runnable r) { synchronized(sGLThreadManager) { mEventQueue.add(r); sGLThreadManager.notifyAll(); } }
在GLThread的guardenRun()方法中有如下代码:
- if (! mEventQueue.isEmpty()) {
- event = mEventQueue.remove(0);
- break;
- }
- ...
- if (event != null) {
- event.run();
- event = null;
- continue;
- }
- class MyGLSurfaceView extends GLSurfaceView {
- private MyRenderer mMyRenderer;
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- queueEvent(new Runnable() {
- // 这个方法会在渲染线程里被调用
- public void run() {
- mMyRenderer.handleDpadCenter();
- }});
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- public boolean onTouchEvent(final MotionEvent event) {
- queueEvent(new Runnable(){
- public void run() {
- mRenderer.setColor(event.getX() / getWidth(),
- event.getY() / getHeight(), 1.0f);
- }});
- return true;
- }
- }
GLSurfaceView源码分析 GLSurfaceView中对于GL环境的操作,除queueEvent是将事件放入队列中然后到GL线程中执行外, 其他方法基本都是在主线程中修改某个状态值(某个属性属性),然后调用 取消GL线程的等待, 在GL线程中根据属性的状态值作不同的操作,并在操作后反馈给主线程,当然有的方法也不需要反馈。 相关类图如下,GLSurfaceView中的EglHelper和GLThread分别实现了上面提到的管理EGL环境和渲染线程的工作,GLSurfaceView的使用者需要实现Renderer接口。
渲染的整体步骤如下:
- 获取EGLDisplay对象,初始化与EGLDisplay 之间的连接
- 获取EGLConfig对象
- 创建EGLContext 实例
- 创建EGLSurface实例
- 连接EGLContext和EGLSurface.
- 是否需要重新申请EGLSurface,如果尺寸发生了变化,此时createEGLSurface为true
- 是否需要申请GLObject,此时createGLinterface为true
- 是否需要生成EGLContext,此时createEGLContext为true
- 尺寸是否变化,sizeChanged为true,此时需要通知观察者
- 一切准备好之后,使用GL指令绘制图形,调用view.mRenderer.onDrawFrame进行真正的渲染
- 最后通过swap把渲染结果显示到屏幕
- 断开并释放与EGLSurface关联的EGLContext对象
- 删除EGLSurface对象
- 删除EGLContext对象
- 终止与EGLDisplay之间的连接
public class GLSurfaceView extends SurfaceView implements SurfaceHolder . Callback2 {
public final static int RENDERMODE_WHEN_DIRTY = 0 ;//按需渲染模式 public final static int RENDERMODE_CONTINUOUSLY = 1 ;//连续渲染模式
private static final GLThreadManager sGLThreadManager = new GLThreadManager() ;
private final WeakReference
public GLSurfaceView (Context context) { super (context); init(); }
public GLSurfaceView (Context context, AttributeSet attrs) { super (context, attrs); init(); }
//调试用的 public void setDebugFlags ( int debugFlags); public int getDebugFlags ();
//设置暂停的时候是否保持EglContext public void setPreserveEGLContextOnPause ( boolean preserveOnPause); public boolean getPreserveEGLContextOnPause ();
//设置渲染器,这个非常重要,渲染工作就依靠渲染器了 //调用此方法会开启一个新的线程,即GL线程 public void setRenderer (Renderer renderer) { checkRenderThreadState();//检查渲染线程是否已经创建了,如果已经创建了就抛出异常 if (mEGLConfigChooser == null ) { mEGLConfigChooser = new SimpleEGLConfigChooser( true );//默认的 } if (mEGLContextFactory == null ) { mEGLContextFactory = new DefaultContextFactory();// } if (mEGLWindowSurfaceFactory == null ) { mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();// } mRenderer = renderer; mGLThread = new GLThread(mThisWeakRef); mGLThread.start(); }
//设置EGLContext工厂,不设置就用默认的 public void setEGLContextFactory (EGLContextFactory factory){ checkRenderThreadState() ; mEGLContextFactory = factory ; }
//设置EGLSurface工厂,不设置就用默认的 public void setEGLWindowSurfaceFactory (EGLWindowSurfaceFactory factory){ checkRenderThreadState() ; mEGLWindowSurfaceFactory = factory ; } //设置EglConfig,一般颜色深度等等,利用此方法设置。不设置就用默认的 public void setEGLConfigChooser (EGLConfigChooser configChooser){ checkRenderThreadState() ; mEGLConfigChooser = configChooser ; }
//内部调用setEGLConfigChooser public void setEGLConfigChooser ( boolean needDepth){ setEGLConfigChooser( new SimpleEGLConfigChooser(needDepth)) ; }
//内部调用setEGLConfigChooser public void setEGLConfigChooser ( int redSize, int greenSize, int blueSize, int alphaSize, int depthSize, int stencilSize){ setEGLConfigChooser( new ComponentSizeChooser(redSize , greenSize , blueSize , alphaSize , depthSize , stencilSize)) ; }
//设置EGLContextVersion,比如2,即OpenGLES2.0 public void setEGLContextClientVersion ( int version){ checkRenderThreadState() ; mEGLContextClientVersion = version ; }
//设置渲染方式,有RENDERMODE_CONTINUOUSLY表示不断渲染 //以及RENDERMODE_WHEN_DIRTY表示在需要的时候才会渲染 //渲染的时候调用requestRender必须在setRenderer后 public void setRenderMode ( int renderMode){ mGLThread .setRenderMode(renderMode) ; }
public int getRenderMode (){ return mGLThread .getRenderMode() ; }
//主动请求渲染 public void requestRender (){ mGLThread .requestRender() ; }
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) ; }
@Override public void surfaceRedrawNeeded (SurfaceHolder holder) { if (mGLThread != null ) { mGLThread.requestRenderAndWait(); } }
//生命周期,一般在Activity、Fragment的onPause中调用 public void onPause (){ mGLThread .onPause() ; }
//生命周期,一般在Activity、Fragment的onResume中调用 public void onResume (){ mGLThread .onResume() ; }
//向GL线程发送一个任务 public void queueEvent (Runnable r){ mGLThread .queueEvent(r) ; }
//附加到Window上时被调用,外部不可调用 protected void onAttachedToWindow (){ super .onAttachedToWindow() ; if ( mDetached && ( mRenderer != null )) { int renderMode = RENDERMODE_CONTINUOUSLY ; if ( mGLThread != null ) { renderMode = mGLThread .getRenderMode() ; } mGLThread = new GLThread( mThisWeakRef ) ; if (renderMode != RENDERMODE_CONTINUOUSLY ) { mGLThread .setRenderMode(renderMode) ; } mGLThread .start() ; } mDetached = false; }
//从Window上被移除时调用,外部不可调用 protected void onDetachedFromWindow (){ if ( mGLThread != null ) { mGLThread .requestExitAndWait() ; } mDetached = true; super .onDetachedFromWindow() ; }
//渲染器接口 public interface Renderer {
//Surface被创建时被调用,通常在此进行渲染的初始化 void onSurfaceCreated(GL10 gl, EGLConfig config);
//Surface大小被改变时被调用 void onSurfaceChanged(GL10 gl, int width, int height);
//执行渲染时被调用,以完成用户渲染工作 void onDrawFrame(GL10 gl);
}
//非常重要的一个EGL帮助类,GL环境的建立依靠此类 private static class EglHelper { public EglHelper (WeakReference
//EGL的初始化,可以参考此方法 public void start () { /* * Get an EGL instance */ mEgl = (EGL10) EGLContext.getEGL();
/* * Get to the default display. */ mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { throw new RuntimeException( "eglGetDisplay failed" ); }
/* * We can now initialize EGL for that display */ int [] version = new int [ 2 ]; if (!mEgl.eglInitialize(mEglDisplay, version)) { throw new RuntimeException( "eglInitialize failed" ); } GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view == null ) { mEglConfig = null ; mEglContext = null ; } else { mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
/* * Create an EGL context. We want to do this as rarely as we can, because an * EGL context is a somewhat heavy object. */ mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); } if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { mEglContext = null ; throwEglException("createContext"); } if (LOG_EGL) { Log.w( "EglHelper" , "createContext " + mEglContext + " tid=" + Thread.currentThread().getId()); }
mEglSurface = null ; }
//创建EGLSurface,使GL的渲染,能够渲染到用户指定的Surface //默认的Surface就是SurfaceHolder的Surface public boolean createSurface () { /* * Check preconditions. */ if (mEgl == null ) { throw new RuntimeException( "egl not initialized" ); } if (mEglDisplay == null ) { throw new RuntimeException( "eglDisplay not initialized" ); } if (mEglConfig == null ) { throw new RuntimeException( "mEglConfig not initialized" ); }
/* * The window size has changed, so we need to create a new * surface. */ destroySurfaceImp();
/* * Create an EGL surface we can render into. */ GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null ) { mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, view.getHolder()); } else { mEglSurface = null ; }
if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { int error = mEgl.eglGetError(); if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { Log.e( "EglHelper" , "createWindowSurface returned EGL_BAD_NATIVE_WINDOW." ); } return false ; }
/* * Before we can issue GL commands, we need to make sure * the context is current and bound to a surface. */ if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { /* * Could not make the context current, probably because the underlying * SurfaceView surface has been destroyed. */ logEglErrorAsWarning( "EGLHelper" , "eglMakeCurrent" , mEgl.eglGetError()); return false ; }
return true ; }
//通过EGL得到GL,然后用户设置了Wrapper的话会给得到的GL做个包装 //同时也会解析一下用户的Debug意图,看看要不要debug GL createGL(){
GL gl = mEglContext.getGL(); GLSurfaceView view = mGLSurfaceViewWeakRef .get() ; if (view != null ) { if (view.mGLWrapper != null ) { gl = view.mGLWrapper.wrap(gl) ; }
if ((view.mDebugFlags & ( DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS )) != 0 ) { int configFlags = 0 ; Writer log = null; if ((view.mDebugFlags & DEBUG_CHECK_GL_ERROR ) != 0 ) { configFlags |= GLDebugHelper. CONFIG_CHECK_GL_ERROR ; } if ((view.mDebugFlags & DEBUG_LOG_GL_CALLS ) != 0 ) { log = new LogWriter() ; } gl = GLDebugHelper. wrap (gl , configFlags , log) ; } } return gl ; }
//绘制完成之后,调用此方法,将绘制的内容输出到前台,让用户可以看到 public int swap (){ if (! mEgl .eglSwapBuffers( mEglDisplay , mEglSurface )) { return mEgl .eglGetError() ; } return EGL10. EGL_SUCCESS ; }
//销毁Surface的方法,具体实现在destroySurfaceImp方法中 public void destroySurface() { destroySurfaceImp() ; }
private void destroySurfaceImp () { if ( mEglSurface != null && mEglSurface != EGL10. EGL_NO_SURFACE ) { mEgl .eglMakeCurrent( mEglDisplay , EGL10. EGL_NO_SURFACE , EGL10. EGL_NO_SURFACE , EGL10. EGL_NO_CONTEXT ) ; GLSurfaceView view = mGLSurfaceViewWeakRef .get() ; if (view != null ) { view.mEGLWindowSurfaceFactory.destroySurface( mEgl , mEglDisplay , mEglSurface ) ; } mEglSurface = null; } } public void finish () { if ( mEglContext != null ) { GLSurfaceView view = mGLSurfaceViewWeakRef .get() ; if (view != null ) { view.mEGLContextFactory.destroyContext( mEgl , mEglDisplay , mEglContext ) ; } mEglContext = null; } if ( mEglDisplay != null ) { mEgl .eglTerminate( mEglDisplay ) ; mEglDisplay = null; } } } ---------------------------------------------------------------------------------------------- //GL线程,此类中存在的方法在GLSurfaceView中都有同名的, 都是提供给GLSurfaceView作为真正的实现调用 static class GLThread extends Thread {
GLSurfaceView中对于GL环境的操作,除queueEvent是将事件放入队列中然后到GL线程中执行外, 其他方法基本都是在主线程中修改某个状态值(下面的某个属性属性),然后调用取消GL线程的等待, 在GL线程中根据属性的状态值作不同的操作,并在操作后反馈给主线程,当然有的方法也不需要反馈。 private boolean mShouldExit; private boolean mExited ; private boolean mRequestPaused ; private boolean mPaused ; private boolean mHasSurface ; private boolean mSurfaceIsBad ; private boolean mWaitingForSurface ; private boolean mHaveEglContext ; private boolean mHaveEglSurface ; private boolean mFinishedCreatingEglSurface ; private boolean mShouldReleaseEglContext ; private int mWidth ; private int mHeight ; private int mRenderMode ; private boolean mRequestRender ; private boolean mWantRenderNotification ; private boolean mRenderComplete ; private ArrayList
// End of member variables protected by the sGLThreadManager monitor. private EglHelper mEglHelper ;
private WeakReference
GLThread (WeakReference
@Override public void run () { setName( "GLThread " + getId()) ; try { guardedRun() ;//处理所有渲染逻辑
} catch (InterruptedException e) { } finally { sGLThreadManager .threadExiting( this ) ; } }
//销毁EglSurface private void stopEglSurfaceLocked (){ if ( mHaveEglSurface ) { mHaveEglSurface = false; mEglHelper .destroySurface() ; } }
//销毁EglContext private void stopEglContextLocked (){ if ( mHaveEglContext ) { mEglHelper .finish() ; mHaveEglContext = false; sGLThreadManager .releaseEglContextLocked( this ) ; } }
// GL线程 都在这个方法里面,这个方法比较复杂 第一步:判断事件队列是否为空,如果有事件需要处理,则直接跳出内循环去处理事件,否则依然在内循环运行 第二步:1.判断是否需要释放EGLSurface, 2.判断是否丢失了Surface,mHasSurface表示当前有没有可用的Surface,mWaitingForSurface表示是否在申请Surface的过程中, 3.是否需要放弃EGLContext 第三步:经过以上的判断之后,程序进入图形渲染前的准备工作,也就是readyToDraw之间的代码 第四步:一旦程序执行到这里也就是跳出了内循环,有两种可能,第一是EventQueue中有需要处理的事件,第二是需要执行渲染工作 private void guardedRun () throws InterruptedException { mEglHelper = new EglHelper(mGLSurfaceViewWeakRef);//初始化 mHaveEglContext = false ; mHaveEglSurface = false ; mWantRenderNotification = false ;
try { GL10 gl = null ; boolean createEglContext = false ; boolean createEglSurface = false ; boolean createGlInterface = false ; boolean lostEglContext = false ; boolean sizeChanged = false ; boolean wantRenderNotification = false ; boolean doRenderNotification = false ; boolean askedToReleaseEglContext = false ; int w = 0 ; int h = 0 ; Runnable event = null ;
while ( true ) { synchronized (sGLThreadManager) { while ( true ) {//死循环,除非主动跳出 //外部请求退出GL线程 if (mShouldExit) { return ; }
/*外部请求在GL线程中处理的事件没有处理完时,就优先处理这些事件*/ if (! mEventQueue.isEmpty()) { event = mEventQueue.remove( 0 ); break ; }
//暂停和恢复状态变化时,onResume和onPause状态变化 boolean pausing = false ; if (mPaused != mRequestPaused) { pausing = mRequestPaused; mPaused = mRequestPaused; /*GLSurfaceView的onPause和onResume都会用wait方法等待GL线程的响应,这时候主线程阻塞。 此处调用notifyAll通知onPause和onResume,放弃主线程的阻塞。 GLSurfaceView中其他很多方法也存在wait方法,基本与此类似 */ sGLThreadManager.notifyAll(); }
// 需要释放EglContext时候执行的工作 if (mShouldReleaseEglContext) { stopEglSurfaceLocked(); stopEglContextLocked(); mShouldReleaseEglContext = false ; askedToReleaseEglContext = true ; }
// EglContext丢失时,销毁EglSurface和EglContext if (lostEglContext) { stopEglSurfaceLocked(); stopEglContextLocked(); lostEglContext = false ; }
// 如果 acitivity 已经暂停, 接收了暂停信号,而且当前EglSurface存在时,销毁EglSurface if (pausing && mHaveEglSurface) { stopEglSurfaceLocked(); }
/*接收了暂停信号,而且当前EglContext存在时,根据用户设置,来决定是否销毁EglContext*/ if (pausing && mHaveEglContext) { GLSurfaceView view = mGLSurfaceViewWeakRef.get(); boolean preserveEglContextOnPause = view == null ? false : view.mPreserveEGLContextOnPause; if (!preserveEglContextOnPause) { stopEglContextLocked(); } }
/*Surface不存在而且当前并没有在等待Surface*/ if ((! mHasSurface) && (! mWaitingForSurface)) { if (mHaveEglSurface) { stopEglSurfaceLocked(); } mWaitingForSurface = true ; mSurfaceIsBad = false ; sGLThreadManager.notifyAll(); }
// Surface存在,而且在等待Surface if (mHasSurface && mWaitingForSurface) { mWaitingForSurface = false ; sGLThreadManager.notifyAll(); }
if (doRenderNotification) { mWantRenderNotification = false ; doRenderNotification = false ; mRenderComplete = true ; sGLThreadManager.notifyAll(); }
// 判断当前环境准备好了渲染执行,否则进入下一轮等待及判断 判断两个关键因素:EGLContext和EGLSurface是否存在并有效,如果没有EGLContext,就需要获取一个, 如果当前有EGLSurface但尺寸发生了变化,那么就需要销毁他并重新申请Surface。 可以渲染图形的条件是: 1.程序当前不处于pause状态, 2.已经成功获得Surface, 3.有合适的尺寸, 4.处于自动持续渲染状态或用户发起了渲染请求 if (readyToDraw()) {
// 没有EglContext就需要借助EglHelper来创建EglContext if (! mHaveEglContext) { if (askedToReleaseEglContext) { askedToReleaseEglContext = false ; } else { try { mEglHelper.start(); } catch (RuntimeException t) { sGLThreadManager.releaseEglContextLocked( this ); throw t; } mHaveEglContext = true ; createEglContext = true ;
sGLThreadManager.notifyAll(); } }
/*有了EglContext,但是没有EglSurface,就需要设置一些状态,以便后续操作*/ if (mHaveEglContext && !mHaveEglSurface) { mHaveEglSurface = true ; createEglSurface = true ; createGlInterface = true ; sizeChanged = true ; }
/*有eglSurface时,需要判断是否需要执行surface sizechange*/ if (mHaveEglSurface) { if (mSizeChanged) { sizeChanged = true ; w = mWidth; h = mHeight; mWantRenderNotification = true ; // Destroy and recreate the EGL surface. createEglSurface = true ;
mSizeChanged = false ; } mRequestRender = false ; sGLThreadManager.notifyAll(); if (mWantRenderNotification) { wantRenderNotification = true ; } //注意此处break,跳出等待的循环 break ; } }
// By design, this is the only place in a GLThread thread where we wait(). sGLThreadManager.wait(); } }
/*外部请求在GL线程中处理的事件没有处理完时,就优先处理这些事件*/ if (event != null ) { event.run(); event = null ; continue ; }
//后续就是根据上面的判断设置,来执行相应的操作 if (createEglSurface) {//EglSurface需要被创建 //创建EglSurface if (mEglHelper.createSurface()) { synchronized (sGLThreadManager) { mFinishedCreatingEglSurface = true ; sGLThreadManager.notifyAll(); } } else { synchronized (sGLThreadManager) { mFinishedCreatingEglSurface = true ; mSurfaceIsBad = true ; sGLThreadManager.notifyAll(); } continue ; } createEglSurface = false ; }
if (createGlInterface) { gl = (GL10) mEglHelper.createGL();
createGlInterface = false ; }
if (createEglContext) {
GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null ) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onSurfaceCreated" ); //调用GLSurfaceView设置的renderer的onSurfceCreated方法 view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } createEglContext = false ; }
//surface大小被改变 if (sizeChanged) { GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null ) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onSurfaceChanged" ); view.mRenderer.onSurfaceChanged(gl, w, h);//通知应用程序尺寸发生了变化 } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } sizeChanged = false ; }
//每帧绘制 { GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null ) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onDrawFrame" ); view.mRenderer.onDrawFrame(gl);//调用应用程序的Renderer渲染 } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } } //提交绘制结果,通过swap把渲染结果显示到屏幕上 int swapError = mEglHelper.swap(); switch (swapError) { case EGL10.EGL_SUCCESS: break ; case EGL11.EGL_CONTEXT_LOST: lostEglContext = true ; break ; default : EglHelper.logEglErrorAsWarning( "GLThread" , "eglSwapBuffers" , swapError);
synchronized (sGLThreadManager) { mSurfaceIsBad = true ; sGLThreadManager.notifyAll(); } break ; }
if (wantRenderNotification) { doRenderNotification = true ; wantRenderNotification = false ; } }
} finally { /* * clean-up everything... */ synchronized (sGLThreadManager) { stopEglSurfaceLocked(); stopEglContextLocked(); } }
}
public boolean ableToDraw () { return mHaveEglContext && mHaveEglSurface && readyToDraw(); }
private boolean readyToDraw () { return (!mPaused) && mHasSurface && (!mSurfaceIsBad) && (mWidth > 0 ) && (mHeight > 0 ) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)); }
//设置渲染方法,见GLSurfaceView的setRenderMode public void setRenderMode ( int renderMode){ if ( !(( RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY )) ) { throw new IllegalArgumentException( "renderMode" ) ; } synchronized ( sGLThreadManager ) { mRenderMode = renderMode ; sGLThreadManager .notifyAll() ; } }
public int getRenderMode (){ synchronized ( sGLThreadManager ) { return mRenderMode ; } }
//请求一次渲染 public void requestRender (){ synchronized ( sGLThreadManager ) { mRequestRender = true; sGLThreadManager .notifyAll() ; } }
//请求一次渲染,并等待渲染完成 public void requestRenderAndWait (){ synchronized ( sGLThreadManager ) { if (Thread. currentThread () == this ) { return; }
mWantRenderNotification = true; mRequestRender = true; mRenderComplete = false;
sGLThreadManager .notifyAll() ;
while (! mExited && ! mPaused && ! mRenderComplete && ableToDraw()) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } }
} } //创建Surface public void surfaceCreated (){ synchronized ( sGLThreadManager ) { mHasSurface = true; mFinishedCreatingEglSurface = false; sGLThreadManager .notifyAll() ; while ( mWaitingForSurface && ! mFinishedCreatingEglSurface && ! mExited ) { try { sGLThreadManager .wait() ; } catch (InterruptedException e) { Thread. currentThread ().interrupt() ; } } } }
//销毁Surface public void surfaceDestroyed (){ synchronized ( sGLThreadManager ) { mHasSurface = false; sGLThreadManager .notifyAll() ; while ((! mWaitingForSurface ) && (! mExited )) { try { sGLThreadManager .wait() ; } catch (InterruptedException e) { Thread. currentThread ().interrupt() ; } } } }
public void onPause (){ synchronized ( sGLThreadManager ) { mRequestPaused = true; sGLThreadManager .notifyAll() ; while ((! mExited ) && (! mPaused )) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } } } } public void onResume (){ synchronized ( sGLThreadManager ) { mRequestPaused = false; mRequestRender = true; mRenderComplete = false; sGLThreadManager .notifyAll() ; while ((! mExited ) && mPaused && (! mRenderComplete )) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } } } }
//Surface的大小被改变时调用 public void onWindowResize ( int w, int h){ synchronized ( sGLThreadManager ) { mWidth = w ; mHeight = h ; mSizeChanged = true; mRequestRender = true; mRenderComplete = false;
if (Thread. currentThread () == this ) { return; }
sGLThreadManager .notifyAll() ;
while (! mExited && ! mPaused && ! mRenderComplete && ableToDraw()) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } } } }
//请求退出渲染线程,并等待退出 public void requestExitAndWait (){ synchronized ( sGLThreadManager ) { mShouldExit = true; sGLThreadManager .notifyAll() ; while (! mExited ) { try { sGLThreadManager .wait() ; } catch (InterruptedException ex) { Thread. currentThread ().interrupt() ; } } } }
//请求回收EglContext public void requestReleaseEglContextLocked (){ mShouldReleaseEglContext = true; sGLThreadManager .notifyAll() ; }
//向GL线程发送一个任务 public void queueEvent (Runnable r){ if (r == null ) { throw new IllegalArgumentException( "r must not be null" ) ; } synchronized ( sGLThreadManager ) { mEventQueue .add(r) ; sGLThreadManager .notifyAll() ; } }
}
//很多方法都会调用此方法,会检查mGLThread不为null, 即保证调用此方法的方法,必须在setRenderer之前调用 private void checkRenderThreadState (){ if ( mGLThread != null ) { throw new IllegalStateException( "setRenderer has already been called for this instance." ) ; } }
//主要就是用来做同步用的,利用Object的wait和notifyAll private static class GLThreadManager {
public synchronized void threadExiting(GLThread thread) { thread. mExited = true; notifyAll() ; }
public void releaseEglContextLocked(GLThread thread) { notifyAll() ; } }
}
EGLHelper readyToDraw后调用了 EGLHelper. start方法初始化,然后跳出readyToDraw后调用了 EGLHelper. createSurface方法创建一个 EglSurface, 最后绘制完成以后 通过 EGLHelper. swap把渲染结果显示到屏幕上。
第一步: EGLHelper. start()方法初始化EGLHelper的内容 public void start() { mEgl = (EGL10) EGLContext.getEGL();//获取一个EGL实例 //获取一个EGLDisplay mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
//初始化EGL并返回版本号 if(!mEgl.eglInitialize(mEglDisplay, version)) { } GLSurfaceView view = mGLSurfaceViewWeakRef.get(); //选取一个配置 mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); //创建EGLContext mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); mEglSurface = null; }
第二步:如果需要创建 EglSurface,调用 mEglHelper.createSurface()方法 public boolean createSurface() { if (LOG_EGL) { Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId()); } /* * Check preconditions. */ if (mEgl == null) { throw new RuntimeException("egl not initialized"); } if (mEglDisplay == null) { throw new RuntimeException("eglDisplay not initialized"); } if (mEglConfig == null) { throw new RuntimeException("mEglConfig not initialized"); } GLSurfaceView view = mGLSurfaceViewWeakRef.get(); mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, view.getHolder());
return true; }
private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, Object nativeWindow) { EGLSurface result = null; result = egl.eglCreateWindowSurface(display, config, nativeWindow, null); return result; }
}
第三步:提交绘制结果,通过mEglHelper.swap()把渲染结果显示到屏幕上 public int swap() { if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { return mEgl.eglGetError(); } return EGL10.EGL_SUCCESS; }
总结GLSurfaceView使用EGL的流程如下: 1.生成一个EGL实例 mEgl = (EGL10) EGLContext.getEGL(); 2.获取一个EGL Display mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 3.初始化EGL并返回版本号 if(!mEgl.eglInitialize(mEglDisplay, version)) {} 4.选取一个配置 mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); 5.创建一个EGLContext mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); 6.创建EGLSurface egl.eglCreateWindowSurface(display, config, nativeWindow, null); 7.通过swap将渲染内容显示到屏幕 mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- android 7.0 有关wifi热点设置信息
- 二、Toolbar
- 弹出对话框--------android Toast 五种情形(无按钮)
- Android(安卓)TextView部分文字实现点击事件
- Android自屏幕底部滑出更多面板的实现
- Android回音噪音处理Demo
- 关于 android:windowSoftInputMode 的设置
- Android(安卓)Manager之MediaRecorder(音视频录制)