Android OpenGL入門(mén)之GLSurfaceView
GLSurfaceView使用
OpenGL ES是是一個(gè)開(kāi)源圖形庫(kù),那么與之相關(guān)的需要一個(gè)東西去顯示畫(huà)面,在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.
可見(jiàn)系統(tǒng)已封裝好一個(gè)View用于渲染畫(huà)面并能進(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接口的類(lèi)
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的線(xiàn)程進(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類(lèi),并在一段邏輯判斷后調(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)通信
- 查詢(xún)繪圖表面的可用類(lèi)型和配置
- 創(chuàng)建繪圖表面
- 在OpenGL ES 3.0和其他圖形渲染API之間同步渲染
- 管理紋理貼圖等渲染資源
EGLDisplay:由于每個(gè)窗口系統(tǒng)都有不同的語(yǔ)義,所以EGL提供基本的不透明類(lèi)型EGLDisplay,封裝了所有系統(tǒng)相關(guān)性,用于和原生窗口系統(tǒng)接口
EGL有如下一些方法:
EGLDisplay eglGetDisplay(Object native_display);
1.打開(kāi)與EGL顯示服務(wù)器的鏈接打開(kāi)與EGL顯示服務(wù)器的鏈接
2.native_display是一個(gè)displayId,指定顯示鏈接,默認(rèn)鏈接為EGL_DEFAULT_DISPLAY
boolean eglInitialize(EGLDisplay display, int[] major_minor)
1.打開(kāi)鏈接后,需要初始化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上下文共享特定類(lèi)型的數(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。如果需要查詢(xún)故障原因,調(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入門(mén)之GLSurfaceView的詳細(xì)內(nèi)容,更多關(guān)于A(yíng)ndroid GLSurfaceView的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Andoroid實(shí)現(xiàn)底部圖片選擇Dialog效果
這篇文章主要介紹了Andoroid實(shí)現(xiàn)底部圖片選擇Dialog效果,需要的朋友可以參考下2017-10-10Android通過(guò)自定義控件實(shí)現(xiàn)360軟件詳情頁(yè)效果
這篇文章主要給大家介紹了Android通過(guò)自定義控件實(shí)現(xiàn)360軟件詳情頁(yè)效果的相關(guān)資料,實(shí)現(xiàn)后的效果非常不錯(cuò),文中也給出了詳細(xì)的示例代碼和介紹,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-05-05Android開(kāi)發(fā)中在TableView上添加懸浮按鈕的方法
如果直接在TableVIewController上貼Button的話(huà)會(huì)導(dǎo)致這個(gè)會(huì)隨之滾動(dòng),下面通過(guò)本文給大家分享在TableView上實(shí)現(xiàn)位置固定懸浮按鈕的兩種方法,對(duì)tableview 懸浮按鈕感興趣的朋友一起學(xué)習(xí)吧2016-11-11Android實(shí)現(xiàn)動(dòng)態(tài)改變app圖標(biāo)的示例代碼
本篇文章主要介紹了Android實(shí)現(xiàn)動(dòng)態(tài)改變app圖標(biāo)的示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09Android實(shí)現(xiàn)的狀態(tài)欄定制和修改方法
這篇文章主要介紹了Android實(shí)現(xiàn)的狀態(tài)欄定制和修改方法,涉及Android針對(duì)狀態(tài)欄屬性設(shè)置的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10Ubuntu中為Android實(shí)現(xiàn)Application Frameworks層增加硬件訪(fǎng)問(wèn)服務(wù)
本文主要介紹Android實(shí)現(xiàn) Application Frameworks層增加硬件訪(fǎng)問(wèn)服務(wù),這里對(duì)實(shí)現(xiàn)增加硬件訪(fǎng)問(wèn)服務(wù)的功能做出了詳細(xì)的工作流程,并提供示例代碼,有需要的小伙伴參考下2016-08-08Hook實(shí)現(xiàn)Android 微信、陌陌 、探探位置模擬(附源碼下載)
這篇文章主要介紹了Hook實(shí)現(xiàn)Android 微信、陌陌 、探探位置模擬(附源碼下載)的相關(guān)資料,需要的朋友可以參考下2017-03-03Android動(dòng)態(tài)更新Menu菜單的實(shí)現(xiàn)過(guò)程
菜單是用戶(hù)界面中最常見(jiàn)的元素之一,使用非常頻繁,下面這篇文章主要給大家介紹了關(guān)于A(yíng)ndroid動(dòng)態(tài)更新Menu菜單的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-0913問(wèn)13答全面學(xué)習(xí)Android View繪制
這篇文章主要為大家詳細(xì)介紹了Android View繪制,13問(wèn)13答幫助大家全面學(xué)習(xí)Android View繪制,感興趣的小伙伴們可以參考一下2016-03-03