电子商务网站建设评价,网站中 点击出现登录框怎么做,seo网站托管,做网站 郑州公司哪家好OpenGL ES 之EGL(6)
简述
EGL是OpenGL ES的封装#xff0c;目的是跨设备跨平台#xff0c;隔离不同平台对窗口不同的实现。上一节我们基本没有使用到EGL#xff0c;因为GLSurfaceView帮助我们处理了相关的逻辑#xff0c;我们这一节来看一下EGL的一些概念以及接口的使用。…OpenGL ES 之EGL(6)
简述
EGL是OpenGL ES的封装目的是跨设备跨平台隔离不同平台对窗口不同的实现。上一节我们基本没有使用到EGL因为GLSurfaceView帮助我们处理了相关的逻辑我们这一节来看一下EGL的一些概念以及接口的使用。 同时我们会介绍GLSurfaceView做了什么是怎么配置EGL等。
EGL接口
1.eglGetDisplay 用于获取EGLDisplay这里会关联原生窗口,EGLDisplay是对设备的抽象。2.eglInitialize(EGLDisplay display, EGLint *majorVersion, EGLint *minorVersion) 初始化函数第一个参数是eglGetDisplay返回值。3.eglChooseConfig EGL会根据设备配置选择合适的Config4.eglCreateWindowSurface 通过前面EGLDisplay和EGLConfig创建EGLSurface5.eglCreateContext 创建EGLContext创建渲染上下文6.eglMakeCurrent 绑定EGLContextEGLSurfaceEGLDisplay之后即可调用openGL ES的api做图像渲染了。7.eglSwapBuffers 交换缓冲区调用后就会将内存中的图像显示到屏幕上。
GLSurfaceView流程
setRenderer
配置了Renderer之后GLSurfaceView启动了一个GLThread线程
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();}// 构造并启动了一个GLThread线程mGLThread new GLThread(renderer);mGLThread.start();
}GLThread
调用了guardedRun。 guardedRun通过一个EglHelper来调用EGL的接口。 guardedRun在一个死循环中死循环中还有一个死循环这里会通过mEglHelper.start来初始化EGL。在EGLSurface创建好后就会跳出这个死循环在外层循环后面的逻辑首次会通过createSurface创建EGLSurface并且回调Renderer.onSurfaceCreated也会检查sizeChanged如果sizeChanged则会回调Renderer.onSurfaceChanged。 每次循环都会回调Renderer.onDrawFrame,在回调onDrawFrame之后会调用mEglHelper.swap来执行交换区。 这里EglHelper的start/createSurface/swap我们接下来看看这几个方法。
private class GLThread extends Thread {// ...public void run() {setName(GLThread getId());if (LOG_THREADS) {DebugLog.i(GLThread, starting tid getId());}try {guardedRun();} catch (InterruptedException e) {// fall thru and exit normally} finally {sGLThreadManager.threadExiting(this);}}
}private void guardedRun() throws InterruptedException {mEglHelper new EglHelper();// ...try {// ...while (true) {synchronized (sGLThreadManager) {while (true) {// ...if ((! mHasSurface) (! mWaitingForSurface)) {if (LOG_SURFACE) {DebugLog.i(GLThread, noticed surfaceView surface lost tid getId());}if (mHaveEglSurface) {stopEglLocked();}mWaitingForSurface true;sGLThreadManager.notifyAll();}// ...// Ready to draw?if ((!mPaused) mHasSurface (mWidth 0) (mHeight 0) (mRequestRender || (mRenderMode RENDERMODE_CONTINUOUSLY))) {if (mHaveEglContext !mHaveEglSurface) {// 检测EGL上下文if (!mEglHelper.verifyContext()) {mEglHelper.finish();mRenderer.onSurfaceLost();mHaveEglContext false;}}if ((! mHaveEglContext) sGLThreadManager.tryAcquireEglSurfaceLocked(this)) {mHaveEglContext true;// 启动EGLHelper.start,这里会做EGL的初始化mEglHelper.start();sGLThreadManager.notifyAll();}// ...if (mHaveEglSurface) {// ... 配置宽高break;}}sGLThreadManager.wait();}} // end of synchronized(sGLThreadManager)if (event ! null) {event.run();event null;continue;}if (mHasFocus) {if (createEglSurface) {// 调用createSurface初始化EGL上下文gl (GL10) mEglHelper.createSurface(getHolder());// ...// 回调Renderer.onSurfaceCreatedmRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);createEglSurface false;framesSinceResetHack 0;}if (sizeChanged) {// ...// 回调Renderer.onSurfaceChangedmRenderer.onSurfaceChanged(gl, w, h);sizeChanged false;}// ...mWatchDog.reset();// 回调Renderer.onDrawFramemRenderer.onDrawFrame(gl);framesSinceResetHack;// 调用eglSwapBuffers交换缓冲区上屏显示if(!mEglHelper.swap()) {// ...stopEglLocked();}}if (wantRenderNotification) {doRenderNotification true;}}} finally {// ... 释放EGL上下文}
}EglHelper
EglHelper就是对EGL对接口进行封装这些EGL的接口作用在前面都介绍过了。
public void start(){mEgl (EGL10) EGLContext.getEGL();// 通过eglGetDisplay获取EglDisplaymEglDisplay mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);// ...int[] version new int[2];// 调用eglInitialize进行初始化if(!mEgl.eglInitialize(mEglDisplay, version)) {throw new RuntimeException(eglInitialize failed);}// 调用eglChooseConfig获取EglConfigmEglConfig mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);// 创建EglContextmEglContext mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);if (mEglContext null || mEglContext EGL10.EGL_NO_CONTEXT) {throwEglException(createContext);}mEglSurface null;
}public GL createSurface(SurfaceHolder holder) {// 如果之前创建过EglSurface直接调用eglMakeCurrent进行关联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);}// 调用createWindowSurface创建EglSurface mEglSurface mEGLWindowSurfaceFactory.createWindowSurface(mEgl,mEglDisplay, mEglConfig, holder);if (mEglSurface null || mEglSurface EGL10.EGL_NO_SURFACE) {throwEglException(createWindowSurface);}// 调用eglMakeCurrent关联if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {throwEglException(eglMakeCurrent);}GL gl mEglContext.getGL();if (mGLWrapper ! null) {gl mGLWrapper.wrap(gl);}// ... 配置debug相关flagreturn gl;
}public boolean swap() {// 调用eglSwapBuffers交换Buffer显示mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);return mEgl.eglGetError() ! EGL11.EGL_CONTEXT_LOST;
}小结
EGL的接口比较简单流程也基本是固定的我们以GLSurfaceView为例介绍了它的使用流程GLSurfaceView就是启动一个线程除了处理固定的EGL上下文初始化还控制了Renderer回调的几个生命周期。 介绍完EGL后我们后面就可以专注于OpenGL ES的api使用了。