Android平臺Gallery2應用分析(一)---背景知識

Android系統概括來講可分爲GUI、多媒體以及網絡相關三個部分,在學習了GUI部分如何去編寫應用外,多媒體系統是接下來重點分析掌握的重點。本文着重介紹Android中的Gallery2應用以及該應用的框架設計。

概要:本文先對Gallery2中涉及的線程池ThreadPool,OpenGL ES的背景知識略作講解。再以Gallery2應用從Launcher點擊到查看圖片的操作過程爲線索, 將依次分析AlbumSetPage、AlbumPage、PhotoPage、PhotoView以及PhotoPage上的觸屏操作代碼流程。

背景知識
1.1 EGL介紹
        EGL是OpenGL ES和底層Native平臺視窗系統之間的接口。EGL是爲OpenGL ES提供平臺獨立性而設計的。OpenGL ES本質上是一個圖形渲染管線的狀態機,而EGL則是用於監控這些狀態以及維護FrameBuffer和其他渲染Surface的外部層。
        EGL的數據類型:
EGL Boolean :EGL_TRUE = 1, EGL_FALSE = 0
EGL int       : int 數據類型
EGLDisplay   : 系統顯示ID或句柄
EGLConfig    : Surface的EGL配置
EGLSurface   : 系統窗口或framebuffer句柄
EGLContext   : OpenGL ES圖形上下文
NativeDisplayType   : Native系統顯示類型
NativeWindowType  : Native系統窗口緩存類型
NativePixmapType   : Native系統framebuffer


OpenGL ES的初始化過程:

         Surface實際上是一個FrameBuffer, 通過EGLSurface eglCreateWindowSurface(…)創建一個可顯示的Surface。系統通常支持另兩種Surface:PixmapSurface和PBufferSurface。這兩種都不是可顯示的Surface。
PixmapSurface:系統內存中的位圖
PBufferSurface:保存在顯存中的幀
應用程序通過OpenGL API進行繪製,一幀完成後,調用eglSwapBuffers來顯示。


1.2 GLSurfaceView
GLSurfaceView是一個視圖,繼承至SurfaceView,它內嵌的surface專門負責OpenGL渲染。GLSurfaceView提供了下列特性:
1> 管理一個surface,這個surface就是一塊特殊的內存,能直接排版到android的視圖view上。
2> 管理一個EGL display,它能讓opengl把內容渲染到上述的surface上。
3> 用戶自定義渲染器(render)。
4> 讓渲染器在獨立的線程裏運作,和UI線程分離。
5> 支持按需渲染(on-demand)和連續渲染(continuous)。
6> 一些可選工具,如調試。
使用GLSurfaceView 
通常會繼承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)

getHolder().setFormat()的參數需要與setEGLConfigChooser的參數相匹配,否則就會失敗。如果想設置surface背景爲透明,代碼參考如下:
surfaceView.setZOrderOnTop(true);
surfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
surfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);


定製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線程想釋放它,渲染線程卻要使用它。)

歡迎轉載和技術交流,轉載請幫忙註明出處,http://blog.csdn.net/discovery_by_joseph,謝謝!




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章