from: http://blog.csdn.net/chenjie19891104/article/details/6311209android
GLSurfaceView是一個視圖,繼承至SurfaceView,它內嵌的surface專門負責OpenGL渲染。緩存
GLSurfaceView提供了下列特性:多線程
1> 管理一個surface,這個surface就是一塊特殊的內存,能直接排版到android的視圖view上。app
2> 管理一個EGL display,它能讓opengl把內容渲染到上述的surface上。工具
3> 用戶自定義渲染器(render)。.net
4> 讓渲染器在獨立的線程裏運做,和UI線程分離。線程
5> 支持按需渲染(on-demand)和連續渲染(continuous)。調試
6> 一些可選工具,如調試。orm
使用GLSurfaceView blog
一般會繼承GLSurfaceView,並重載一些和用戶輸入事件有關的方法。若是你不須要重載事件方法,GLSurfaceView也能夠直接使用, 你可使用set方法來爲該類提供自定義的行爲。例如,GLSurfaceView的渲染被委託給渲染器在獨立的渲染線程裏進行,這一點和普通視圖不一 樣,setRenderer(Renderer)設置渲染器。
初始化GLSurfaceView
初始化過程其實僅須要你使用setRenderer(Renderer)設置一個渲染器(render)。固然,你也能夠修改GLSurfaceView一些默認配置。
* setDebugFlags(int)
* setEGLConfigChooser(boolean)
* setEGLConfigChooser(EGLConfigChooser)
* setEGLConfigChooser(int, int, int, int, int, int)
* setGLWrapper(GLWrapper)
定製android.view.Surface
GLSurfaceView默認會建立像素格式爲PixelFormat.RGB_565的surface。若是須要透明效果,調用 getHolder().setFormat(PixelFormat.TRANSLUCENT)。透明(TRANSLUCENT)的surface的像 素格式都是32位,每一個色彩單元都是8位深度,像素格式是設備相關的,這意味着它多是ARGB、RGBA或其它。
選擇EGL配置
Android設備每每支持多種EGL配置,可使用不一樣數目的通道(channel),也能夠指定每一個通道具備不一樣數目的位(bits)深度。所以, 在渲染器工做以前就應該指定EGL的配置。GLSurfaceView默認EGL配置的像素格式爲RGB_656,16位的深度緩存(depth buffer),默認不開啓遮罩緩存(stencil buffer)。
若是你要選擇不一樣的EGL配置,請使用setEGLConfigChooser方法中的一種。
調試行爲
你能夠調用調試方法setDebugFlags(int)或setGLWrapper(GLSurfaceView.GLWrapper)來自定義 GLSurfaceView一些行爲。在setRenderer方法以前或以後均可以調用調試方法,不過最好是在以前調用,這樣它們能當即生效。
設置渲染器
總之,你必須調用setRenderer(GLSurfaceView.Renderer)來註冊一個GLSurfaceView.Renderer渲染器。渲染器負責真正的GL渲染工做。
渲染模式
渲染器設定以後,你可使用setRenderMode(int)指定渲染模式是按需(on demand)仍是連續(continuous)。默認是連續渲染。
Activity生命週期
Activity窗口暫停(pause)或恢復(resume)時,GLSurfaceView都會收到通知,此時它的onPause方法和 onResume方法應該被調用。這樣作是爲了讓GLSurfaceView暫停或恢復它的渲染線程,以便它及時釋放或重建OpenGL的資源。
事件處理
爲了處理事件,通常都是繼承GLSurfaceView類並重載它的事件方法。可是因爲GLSurfaceView是多線程操做,因此須要一些特殊的處 理。因爲渲染器在獨立的渲染線程裏,你應該使用Java的跨線程機制跟渲染器通信。queueEvent(Runnable)方法就是一種相對簡單的操 做,例以下面的例子。
class MyGLSurfaceView extends GLSurfaceView {
private MyRenderer mMyRenderer;
public void start() {
mMyRenderer = ...;
setRenderer(mMyRenderer);
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
queueEvent(new Runnable() {
// 這個方法會在渲染線程裏被調用
public void run() {
mMyRenderer.handleDpadCenter();
}});
return true;
}
return super.onKeyDown(keyCode, event);
}
}
(注:若是在UI線程裏調用渲染器的方法,很容易收到「call to OpenGL ES API with no current context」的警告,典型的誤區就是在鍵盤或鼠標事件方法裏直接調用opengl es的API,由於UI事件和渲染繪製在不一樣的線程裏。更甚者,這種狀況下調用glDeleteBuffers這種釋放資源的方法,可能引發程序的崩潰, 由於UI線程想釋放它,渲染線程卻要使用它。)