Android OpenGL入門之GLSurfaceView
GLSurfaceView使用
OpenGL ES是是一個(gè)開源圖形庫(kù),那么與之相關(guān)的需要一個(gè)東西去顯示畫面,在android里,opengl包里提供了一個(gè)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)已封裝好一個(gè)View用于渲染畫面并能進(jìn)行相應(yīng)設(shè)置。
使用步驟如下:
1.創(chuàng)建定義一個(gè)GLSurfaceView
2.調(diào)用GLSurfaceView的setEGLContextClientVersion設(shè)置版本號(hào),可設(shè)為2
3.onResume 和 onPause分別調(diào)用GLSurfaceView相應(yīng)的生命周期方法
4.調(diào)用GLSurfaceView的setRender設(shè)置自己實(shí)現(xiàn)GLSurfaceView.Render接口的類
5.Render接口有3個(gè)方法,分別是SurfaceCreated時(shí)候進(jìn)行相應(yīng)的初始化工作,SurfaceChange時(shí)候高寬的適配以及具體的DrawFrame方法
- onSurfaceCreated(GL10 gl, EGLConfig config);
- onSurfaceChanged(GL10 gl, int width, int height);
- onDrawFrame(GL10 gl);
GLSurfaceView詳細(xì)分析:
1.GLSurfaceView在構(gòu)造函數(shù)中調(diào)用init()設(shè)置如上3個(gè)回掉函數(shù)
private void init() {
SurfaceHolder holder = getHolder();
holder.addCallback(this);
}
2.setRender會(huì)進(jìn)行一些默認(rèn)的設(shè)置,并生成一個(gè)GLThread的線程進(jìn)行渲染繪制相關(guān)操作,繪制的內(nèi)容默認(rèn)情況下依舊是繪制到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 了一個(gè)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);
}
...
}
這里有如下幾個(gè)重要方法,最終會(huì)調(diào)用到C++層去初始化相關(guān)的渲染界面
- EGLContext.getEGL()
- eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY)
- eglInitialize(mEglDisplay, version)
- createContext()
5.在guardedRun() start()調(diào)用后會(huì)調(diào)用EglHelper.createSurface()方法,最終也會(huì)調(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相關(guān)知識(shí)
EGL用于管理繪圖表面,有如下機(jī)制
- 與設(shè)備的原生窗口系統(tǒng)通信
- 查詢繪圖表面的可用類型和配置
- 創(chuàng)建繪圖表面
- 在OpenGL ES 3.0和其他圖形渲染API之間同步渲染
- 管理紋理貼圖等渲染資源
EGLDisplay:由于每個(gè)窗口系統(tǒng)都有不同的語(yǔ)義,所以EGL提供基本的不透明類型EGLDisplay,封裝了所有系統(tǒng)相關(guān)性,用于和原生窗口系統(tǒng)接口
EGL有如下一些方法:
EGLDisplay eglGetDisplay(Object native_display);
1.打開與EGL顯示服務(wù)器的鏈接打開與EGL顯示服務(wù)器的鏈接
2.native_display是一個(gè)displayId,指定顯示鏈接,默認(rèn)鏈接為EGL_DEFAULT_DISPLAY
boolean eglInitialize(EGLDisplay display, int[] major_minor)
1.打開鏈接后,需要初始化EGL
2.display:getDisplay返回的值
3.主次版本號(hào)
boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, EGLConfig[] configs, int config_size, int[] num_config);
1.讓EGL選擇匹配的EGLConfig
2.具體就是調(diào)用選擇配置,配置細(xì)節(jié)暫不敘述
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
1.創(chuàng)建渲染上下文
2.display:指定的顯示鏈接
3.config:指定的配置
4.share_context:允許多個(gè)EGL上下文共享特定類型的數(shù)據(jù);使用EGL_NO_CONTEXT表示沒(méi)有共享
5.attrib_list:指定創(chuàng)建上下文使用的屬性列表;只有一個(gè)可接受的屬性:EGL_CONTEXT_CLIENT_VERSION表示指定與你所使用的OpenGL ES版本
6.eglCreateContext成功時(shí),它返回一個(gè)指向新創(chuàng)建上下文的句柄。
EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
1.有了符合渲染要求的EGLConfig,就可調(diào)用此函數(shù)創(chuàng)建一個(gè)窗口
2.屬性同上
int eglGetError();
1.EGL函數(shù)成功時(shí)返回EGL_TRUE,否則返回EGL_FALSE。如果需要查詢故障原因,調(diào)用eglGetError()得到返回錯(cuò)誤碼。
boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context);
1.因一個(gè)應(yīng)用程序可能創(chuàng)建多個(gè)EGLContext用于不同的用途,所以需要關(guān)聯(lián)特定的EGLContext和渲染表面即:指定當(dāng)前上下文
整個(gè)大概流程就如上所述調(diào)用下來(lái)。
以上就是Android OpenGL入門之GLSurfaceView的詳細(xì)內(nèi)容,更多關(guān)于Android GLSurfaceView的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android進(jìn)程運(yùn)行中權(quán)限被收回導(dǎo)致關(guān)閉的問(wèn)題解決
在Android開發(fā)中我們可能會(huì)遇到這樣的問(wèn)題,進(jìn)程還在運(yùn)行著某些權(quán)限卻被收回了,這就導(dǎo)致進(jìn)程崩潰被迫關(guān)閉,本篇文章將帶你了解這個(gè)問(wèn)題的發(fā)生與解決方法2021-10-10
Android實(shí)現(xiàn)二級(jí)列表購(gòu)物車功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)二級(jí)列表購(gòu)物車功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Android EditText實(shí)現(xiàn)輸入表情
editText是TextView的子類,TextView能用的工具EditText都能用,接下來(lái)通過(guò)實(shí)例代碼給大家分享Android EditText實(shí)現(xiàn)輸入表情功能,感興趣的朋友一起看看吧2017-08-08
Android實(shí)現(xiàn)滑動(dòng)折疊Header全流程詳解
這篇文章主要介紹了Android實(shí)現(xiàn)滑動(dòng)折疊Header,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-11-11
在Android設(shè)備上搭建Web服務(wù)器的方法
本篇文章主要介紹了在Android設(shè)備上搭建Web服務(wù)器的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04
Android實(shí)現(xiàn)ImageView圖片縮放和拖動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)ImageView圖片縮放和拖動(dòng)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Android ListView的Item點(diǎn)擊效果的定制
這篇文章主要介紹了Android ListView的Item點(diǎn)擊效果的定制的相關(guān)資料,需要的朋友可以參考下2017-07-07

