Android OpenGL入門之GLSurfaceView
GLSurfaceView使用
OpenGL ES是是一個開源圖形庫,那麼與之相關的需要一個東西去顯示畫面,在android裡,opengl包裡提供瞭一個View叫GLSurfaceView,它的定義如下:
An implementation of SurfaceView that uses the dedicated surface for
displaying OpenGL rendering.
它的特性如下:
- Manages a surface, which is a special piece of memory that can be
- composited into the Android view system.
- Manages an EGL display, which enables OpenGL to render into a surface.
- Accepts a user-provided Renderer object that does the actual rendering.
- Renders on a dedicated thread to decouple rendering performance from the UI thread.
- Supports both on-demand and continuous rendering.
- Optionally wraps, traces, and/or error-checks the renderer’s OpenGL calls.
可見系統已封裝好一個View用於渲染畫面並能進行相應設置。
使用步驟如下:
1.創建定義一個GLSurfaceView
2.調用GLSurfaceView的setEGLContextClientVersion設置版本號,可設為2
3.onResume 和 onPause分別調用GLSurfaceView相應的生命周期方法
4.調用GLSurfaceView的setRender設置自己實現GLSurfaceView.Render接口的類
5.Render接口有3個方法,分別是SurfaceCreated時候進行相應的初始化工作,SurfaceChange時候高寬的適配以及具體的DrawFrame方法
- onSurfaceCreated(GL10 gl, EGLConfig config);
- onSurfaceChanged(GL10 gl, int width, int height);
- onDrawFrame(GL10 gl);
GLSurfaceView詳細分析:
1.GLSurfaceView在構造函數中調用init()設置如上3個回掉函數
private void init() { SurfaceHolder holder = getHolder(); holder.addCallback(this); }
2.setRender會進行一些默認的設置,並生成一個GLThread的線程進行渲染繪制相關操作,繪制的內容默認情況下依舊是繪制到SurfaceView所提供的Surface上
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(); }
3.GLThread的run()方法裡調用瞭guardedRun()方法,在guardedRun方法裡new 瞭一個EglHelper類,並在一段邏輯判斷後調用瞭EglHelper的start方法。
4.EglHelper.start()方法裡
public void start() { mEgl = (EGL10) EGLContext.getEGL(); mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { throw new RuntimeException("eglGetDisplay failed"); } 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); mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); } ... }
這裡有如下幾個重要方法,最終會調用到C++層去初始化相關的渲染界面
- EGLContext.getEGL()
- eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY)
- eglInitialize(mEglDisplay, version)
- createContext()
5.在guardedRun() start()調用後會調用EglHelper.createSurface()方法,最終也會調用到C++層。
public boolean createSurface() { //Check preconditions. //window size has changed, 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;} ... int error = mEgl.eglGetError(); ... if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError()); return false; } return true; }
- createWindowSurface
- eglGetError
- eglMakeCurrent
EGL相關知識
EGL用於管理繪圖表面,有如下機制
- 與設備的原生窗口系統通信
- 查詢繪圖表面的可用類型和配置
- 創建繪圖表面
- 在OpenGL ES 3.0和其他圖形渲染API之間同步渲染
- 管理紋理貼圖等渲染資源
EGLDisplay:由於每個窗口系統都有不同的語義,所以EGL提供基本的不透明類型EGLDisplay,封裝瞭所有系統相關性,用於和原生窗口系統接口
EGL有如下一些方法:
EGLDisplay eglGetDisplay(Object native_display);
1.打開與EGL顯示服務器的鏈接打開與EGL顯示服務器的鏈接
2.native_display是一個displayId,指定顯示鏈接,默認鏈接為EGL_DEFAULT_DISPLAY
boolean eglInitialize(EGLDisplay display, int[] major_minor)
1.打開鏈接後,需要初始化EGL
2.display:getDisplay返回的值
3.主次版本號
boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, EGLConfig[] configs, int config_size, int[] num_config);
1.讓EGL選擇匹配的EGLConfig
2.具體就是調用選擇配置,配置細節暫不敘述
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
1.創建渲染上下文
2.display:指定的顯示鏈接
3.config:指定的配置
4.share_context:允許多個EGL上下文共享特定類型的數據;使用EGL_NO_CONTEXT表示沒有共享
5.attrib_list:指定創建上下文使用的屬性列表;隻有一個可接受的屬性:EGL_CONTEXT_CLIENT_VERSION表示指定與你所使用的OpenGL ES版本
6.eglCreateContext成功時,它返回一個指向新創建上下文的句柄。
EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
1.有瞭符合渲染要求的EGLConfig,就可調用此函數創建一個窗口
2.屬性同上
int eglGetError();
1.EGL函數成功時返回EGL_TRUE,否則返回EGL_FALSE。如果需要查詢故障原因,調用eglGetError()得到返回錯誤碼。
boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context);
1.因一個應用程序可能創建多個EGLContext用於不同的用途,所以需要關聯特定的EGLContext和渲染表面即:指定當前上下文
整個大概流程就如上所述調用下來。
以上就是Android OpenGL入門之GLSurfaceView的詳細內容,更多關於Android GLSurfaceView的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- None Found