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.
可見系統(tǒng)已封裝好一個View用于渲染畫面并能進行相應設置。
使用步驟如下:
1.創(chuàng)建定義一個GLSurfaceView
2.調(diào)用GLSurfaceView的setEGLContextClientVersion設置版本號,可設為2
3.onResume 和 onPause分別調(diào)用GLSurfaceView相應的生命周期方法
4.調(diào)用GLSurfaceView的setRender設置自己實現(xiàn)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在構(gòu)造函數(shù)中調(diào)用init()設置如上3個回掉函數(shù)
private void init() { SurfaceHolder holder = getHolder(); holder.addCallback(this); }
2.setRender會進行一些默認的設置,并生成一個GLThread的線程進行渲染繪制相關操作,繪制的內(nèi)容默認情況下依舊是繪制到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()方法里調(diào)用了guardedRun()方法,在guardedRun方法里new 了一個EglHelper類,并在一段邏輯判斷后調(diào)用了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); } ... }
這里有如下幾個重要方法,最終會調(diào)用到C++層去初始化相關的渲染界面
- EGLContext.getEGL()
- eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY)
- eglInitialize(mEglDisplay, version)
- createContext()
5.在guardedRun() start()調(diào)用后會調(diào)用EglHelper.createSurface()方法,最終也會調(diào)用到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用于管理繪圖表面,有如下機制
- 與設備的原生窗口系統(tǒng)通信
- 查詢繪圖表面的可用類型和配置
- 創(chuàng)建繪圖表面
- 在OpenGL ES 3.0和其他圖形渲染API之間同步渲染
- 管理紋理貼圖等渲染資源
EGLDisplay:由于每個窗口系統(tǒng)都有不同的語義,所以EGL提供基本的不透明類型EGLDisplay,封裝了所有系統(tǒng)相關性,用于和原生窗口系統(tǒng)接口
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.具體就是調(diào)用選擇配置,配置細節(jié)暫不敘述
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
1.創(chuàng)建渲染上下文
2.display:指定的顯示鏈接
3.config:指定的配置
4.share_context:允許多個EGL上下文共享特定類型的數(shù)據(jù);使用EGL_NO_CONTEXT表示沒有共享
5.attrib_list:指定創(chuàng)建上下文使用的屬性列表;只有一個可接受的屬性:EGL_CONTEXT_CLIENT_VERSION表示指定與你所使用的OpenGL ES版本
6.eglCreateContext成功時,它返回一個指向新創(chuàng)建上下文的句柄。
EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
1.有了符合渲染要求的EGLConfig,就可調(diào)用此函數(shù)創(chuàng)建一個窗口
2.屬性同上
int eglGetError();
1.EGL函數(shù)成功時返回EGL_TRUE,否則返回EGL_FALSE。如果需要查詢故障原因,調(diào)用eglGetError()得到返回錯誤碼。
boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context);
1.因一個應用程序可能創(chuàng)建多個EGLContext用于不同的用途,所以需要關聯(lián)特定的EGLContext和渲染表面即:指定當前上下文
整個大概流程就如上所述調(diào)用下來。
以上就是Android OpenGL入門之GLSurfaceView的詳細內(nèi)容,更多關于Android GLSurfaceView的資料請關注腳本之家其它相關文章!
相關文章
Andoroid實現(xiàn)底部圖片選擇Dialog效果
這篇文章主要介紹了Andoroid實現(xiàn)底部圖片選擇Dialog效果,需要的朋友可以參考下2017-10-10Android通過自定義控件實現(xiàn)360軟件詳情頁效果
這篇文章主要給大家介紹了Android通過自定義控件實現(xiàn)360軟件詳情頁效果的相關資料,實現(xiàn)后的效果非常不錯,文中也給出了詳細的示例代碼和介紹,需要的朋友可以參考借鑒,下面來一起看看吧。2017-05-05Android開發(fā)中在TableView上添加懸浮按鈕的方法
如果直接在TableVIewController上貼Button的話會導致這個會隨之滾動,下面通過本文給大家分享在TableView上實現(xiàn)位置固定懸浮按鈕的兩種方法,對tableview 懸浮按鈕感興趣的朋友一起學習吧2016-11-11Android實現(xiàn)動態(tài)改變app圖標的示例代碼
本篇文章主要介紹了Android實現(xiàn)動態(tài)改變app圖標的示例代碼,具有一定的參考價值,有興趣的可以了解一下2017-09-09Android實現(xiàn)的狀態(tài)欄定制和修改方法
這篇文章主要介紹了Android實現(xiàn)的狀態(tài)欄定制和修改方法,涉及Android針對狀態(tài)欄屬性設置的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10Ubuntu中為Android實現(xiàn)Application Frameworks層增加硬件訪問服務
本文主要介紹Android實現(xiàn) Application Frameworks層增加硬件訪問服務,這里對實現(xiàn)增加硬件訪問服務的功能做出了詳細的工作流程,并提供示例代碼,有需要的小伙伴參考下2016-08-08Hook實現(xiàn)Android 微信、陌陌 、探探位置模擬(附源碼下載)
這篇文章主要介紹了Hook實現(xiàn)Android 微信、陌陌 、探探位置模擬(附源碼下載)的相關資料,需要的朋友可以參考下2017-03-03Android動態(tài)更新Menu菜單的實現(xiàn)過程
菜單是用戶界面中最常見的元素之一,使用非常頻繁,下面這篇文章主要給大家介紹了關于Android動態(tài)更新Menu菜單的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-09-09