Android EGL

部分內(nèi)容摘自其他博客定枷,請見最下[參考資料]

首先來看看Android官方對EGL的解釋:

OpenGL ES 定義了一個(gè)渲染圖形的 API伺帘,但沒有定義窗口系統(tǒng)园担。為了讓 GLES 能夠適合各種平臺奏纪,GLES 將與知道如何通過操作系統(tǒng)創(chuàng)建和訪問窗口的庫結(jié)合使用腌乡。用于 Android 的庫稱為 EGL京髓。如果要繪制紋理多邊形航缀,應(yīng)使用 GLES 調(diào)用;如果要在屏幕上進(jìn)行渲染朵锣,應(yīng)使用 EGL 調(diào)用谬盐。

OpenGL ES 是Android繪圖API,但OpenGL ES是平臺通用的诚些,在特定設(shè)備上使用需要一個(gè)中間層做適配飞傀,這個(gè)中間層就是EGL。


EGL架構(gòu)
  • Display(EGLDisplay) 是對實(shí)際顯示設(shè)備的抽象诬烹。
  • Surface(EGLSurface)是對用來存儲圖像的內(nèi)存區(qū)域 FrameBuffer 的抽象砸烦,包括 Color Buffer, Stencil Buffer 绞吁,Depth Buffer幢痘。
  • Context (EGLContext) 存儲 OpenGL ES繪圖的一些狀態(tài)信息。

Android中的OpenGL 與EGL
Android 2.0版本之后圖形系統(tǒng)的底層渲染均由OpenGL負(fù)責(zé)家破,OpenGL除了負(fù)責(zé)處理3D API調(diào)用颜说,還需負(fù)責(zé)管理顯示內(nèi)存及處理Android SurfaceFlinger或上層應(yīng)用對其發(fā)出的2D API調(diào)用請求购岗。

  • 本地代碼:
    frameworks/native/opengl/libs/EGL
    Android EGL框架,負(fù)責(zé)加載OpenGL函數(shù)庫和EGL本地實(shí)現(xiàn)门粪。
    frameworks/native/opengl/libagl
    Android提供的OpenGL軟件庫

  • JNI代碼:
    frameworks/base/core/jni/com_google_android_gles_jni_EGLImpl.cpp
    EGL本地代碼的JNI調(diào)用接口
    frameworks/base/core/jni/com_google_android_gles_jni_GLImpl.cpp
    frameworks/base/core/jni/android_opengl_GLESXXX.cpp
    OpenGL功能函數(shù)的JNI調(diào)用接口

  • Java代碼:
    frameworks/base/opengl/java/javax/microedition/khronos/egl
    frameworks/base/opengl/java/javax/microedition/khronos/opengles
    frameworks/base/opengl/java/com/google/android/gles_jni/
    frameworks/base/opengl/java/android/opengl
    EGL和OpenGL的Java層接口喊积,提供給應(yīng)用開發(fā)者,通過JNI方式調(diào)用底層函數(shù)玄妈。

首先從Native代碼入手: frameworks/native/opengl/libs/EGL乾吻,該目錄下文件如圖所示:


frameworks/native/opengl/libs/EGL

依次解析該目錄下各個(gè)文件的作用,由于文件缺少注釋拟蜻,只能從代碼解讀含義:
eglApi.cpp:提供暴露給上層的API绎签。包含EGL對象的創(chuàng)建、配置酝锅、銷毀等操作诡必。

初始化EGL
OpenGL ES的初始化過程(EGL初始化)如下圖所示意:
Display → Config → Surface

Context

Application → OpenGL Command

  1. 獲取Display。
    獲得Display要調(diào)用EGLboolean eglGetDisplay(NativeDisplay dpy)屈张,參數(shù)一般為 EGL_DEFAULT_DISPLAY 擒权。

  2. 初始化egl。
    調(diào)用 EGLboolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)阁谆,該函數(shù)會進(jìn)行一些內(nèi)部初始化工作碳抄,并傳回EGL版本號(major.minor)。
    開機(jī)時(shí)打出的信息:
    如下信息可以由const char * eglQueryString (EGLDisplay dpy, EGLint name);給出场绿,name可以是EGL_VENDOR, EGL_VERSION, 或者EGL_EXTENSIONS 剖效。該函數(shù)常用來查詢當(dāng)前版本EGL實(shí)現(xiàn)了哪些擴(kuò)展,方便向下兼容焰盗。

SurfaceFlinger: EGL information:
SurfaceFlinger: vendor    : Android
SurfaceFlinger: version   : 1.4 Android META-EGL
SurfaceFlinger: extensions: EGL_KHR_get_all_proc_addresses EGL_ANDROID_presentation_time EGL_KHR_swap_buffers_with_damage EGL_ANDROID_get_native_client_buffer EGL_ANDROID_front_buffer_auto_refresh EGL_ANDROID_get_frame_timestamps EGL_KHR_image EGL_KHR_image_base EGL_KHR_gl_colorspace EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_gl_renderbuffer_image EGL_KHR_fence_sync EGL_KHR_create_context EGL_KHR_config_attribs EGL_KHR_surfaceless_context EGL_EXT_create_context_robustness EGL_ANDROID_image_native_buffer EGL_KHR_wait_sync EGL_ANDROID_recordable EGL_KHR_partial_update EGL_KHR_mutable_render_buffer EGL_IMG_context_priority 
SurfaceFlinger: Client API: OpenGL_ES
SurfaceFlinger: EGLSurface: 8-8-8-8, config=0x785f32d008
SurfaceFlinger: OpenGL ES informations:
SurfaceFlinger: vendor    : ARM
SurfaceFlinger: renderer  : Mali-T860
SurfaceFlinger: version   : OpenGL ES 3.2 v1.r18p0-00cet0.e348142bb0bcdf18abb600a2670c56a1
SurfaceFlinger: extensions: GL_EXT_debug_marker GL_ARM_rgba8 GL_ARM_mali_shader_binary GL_OES_depth24 GL_OES_depth_texture GL_OES_depth_texture_cube_map GL_OES_packed_depth_stencil GL_OES_rgb8_rgba8 GL_EXT_read_format_bgra GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_standard_derivatives GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_EGL_image_external_essl3 GL_OES_EGL_sync GL_OES_texture_npot GL_OES_vertex_half_float GL_OES_required_internalformat GL_OES_vertex_array_object GL_OES_mapbuffer GL_EXT_texture_format_BGRA8888 GL_EXT_texture_rg GL_EXT_texture_type_2_10_10_10_REV GL_OES_fbo_render_mipmap GL_OES_element_index_uint GL_EXT_shadow_samplers GL_OES_texture_compression_astc GL_KHR_texture_compression_astc_ldr GL_KHR_texture_compression_astc_hdr GL_KHR_texture_compression_astc_sliced_3d GL_KHR_debug GL_EXT_occlusion_query_boolean GL_EXT_disjoint_timer_query GL_EXT_blend_minmax GL_EXT_discard_framebuffer GL_OES_get_prog...
SurfaceFlinger: GL_MAX_TEXTURE_SIZE = 8192
SurfaceFlinger: GL_MAX_VIEWPORT_DIMS = 8192
  1. 選擇Config璧尸。
    Config實(shí)際指的是FrameBuffer的參數(shù),
    一般用EGLboolean eglChooseConfig(EGLDisplay dpy, const EGLint * attr_list, EGLConfig * config, EGLint config_size, EGLint *num_config)熬拒,其中attr_list是以EGL_NONE結(jié)束的參數(shù)數(shù)組爷光,通常以id,value依次存放,對于個(gè)別標(biāo)識性的屬性可以只有 id澎粟,沒有value蛀序。另一個(gè)辦法是用EGLboolean eglGetConfigs(EGLDisplay dpy, EGLConfig * config, EGLint config_size, EGLint *num_config) 來獲得所有config。
    這兩個(gè)函數(shù)都會返回不多于config_size個(gè)Config活烙,結(jié)果保存在config[]中徐裸,系統(tǒng)的總Config個(gè)數(shù)保存 在num_config中。
    可以利用eglGetConfig()中間兩個(gè)參數(shù)為0來查詢系統(tǒng)支持的Config總個(gè)數(shù)啸盏。Config有眾多的Attribute重贺,這些Attribute決定FrameBuffer的格式和能力,通過eglGetConfigAttrib ()來讀取,但不能修改气笙。

  2. 構(gòu)造Surface
    Surface實(shí)際上就是一個(gè)FrameBuffer次企,也就是渲染目的地,通過EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig confg, NativeWindow win, EGLint *cfg_attr)來創(chuàng)建一個(gè)可實(shí)際顯示的Surface健民。
    系統(tǒng)通常還支持另外兩種Surface:PixmapSurface和PBufferSurface抒巢,這兩種都不是可顯示的Surface贫贝,PixmapSurface是保存在系統(tǒng)內(nèi)存中的位圖秉犹,PBuffer則是保存在顯存中的幀。
    對于這兩種surface稚晚,Android系統(tǒng)中崇堵,支持PBufferSurface。Surface也有一些attribute客燕,基本上都可以顧名思義鸳劳,

EGL_HEIGHT EGL_WIDTH EGL_LARGEST_PBUFFER
EGL_TEXTURE_FORMAT EGL_TEXTURE_TARGET
EGL_MIPMAP_TEXTURE EGL_MIPMAP_LEVEL

通過eglSurfaceAttrib()設(shè)置、eglQuerySurface()讀取也搓。

  1. 創(chuàng)建Context
    OpenGL ES的pipeline從程序的角度看就是一個(gè)狀態(tài)機(jī)赏廓,有當(dāng)前的顏色、紋理坐標(biāo)傍妒、變換矩陣幔摸、絢染模式等一大堆狀態(tài),這些狀態(tài)作用于OpenGL API程序提交的頂點(diǎn)坐標(biāo)等圖元從而形成幀緩沖內(nèi)的像素颤练。在OpenGL的編程接口中既忆,Context就代表這個(gè)狀態(tài)機(jī),OpenGL API程序的主要工作就是向Context提供圖元嗦玖、設(shè)置狀態(tài)患雇,偶爾也從Context里獲取一些信息。
    可以用EGLContext eglCreateContext(EGLDisplay dpy, EGLSurface write, EGLSurface read, EGLContext * share_list)來創(chuàng)建一個(gè)Context宇挫。

  2. EGL變量之間的綁定
    boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context)
    該接口將申請到的display苛吱,draw(surface)和 context進(jìn)行了綁定。也就是說器瘪,在context下的OpenGLAPI指令將draw(surface)作為其渲染最終目的地翠储。而display作為draw(surface)的前端顯示。調(diào)用后娱局,當(dāng)前線程使用的EGLContex為context彰亥。

  3. 繪制。
    應(yīng)用程序通過OpenGL API進(jìn)行繪制衰齐,一幀完成之后任斋,調(diào)用eglSwapBuffers(EGLDisplay dpy, EGLContext ctx)來顯示。

If surface is a window surface, eglSwapBuffers posts its color buffer to the associated native window.
The contents of ancillary buffers are always undefined after calling eglSwapBuffers. The contents of the color buffer are left unchanged if the value of the EGL_SWAP_BEHAVIOR attribute of surface is EGL_BUFFER_PRESERVED, and are undefined if the value is EGL_BUFFER_DESTROYED. The value of EGL_SWAP_BEHAVIOR can be set for some surfaces using eglSurfaceAttrib.
eglSwapBuffers performs an implicit flush operation on the context (glFlush for an OpenGL ES or OpenGL context, vgFlush for an OpenVG context) bound to surface before swapping. Subsequent client API commands may be issued on that context immediately after calling eglSwapBuffers, but are not executed until the buffer exchange is completed.
If surface is a pixel buffer or a pixmap, eglSwapBuffers has no effect, and no error is generated.

看看frameworks/native/opengl/libagl/egl.cpp對eglSwapBuffers的實(shí)現(xiàn):

EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
    egl_surface_t* d = static_cast<egl_surface_t*>(draw);

    ...

    // post the surface
    d->swapBuffers();

    // if it's bound to a context, update the buffer
    if (d->ctx != EGL_NO_CONTEXT) {
        d->bindDrawSurface((ogles_context_t*)d->ctx);
        // if this surface is also the read surface of the context
        // it is bound to, make sure to update the read buffer as well.
        // The EGL spec is a little unclear about this.
        egl_context_t* c = egl_context_t::context(d->ctx);
        if (c->read == draw) {
            d->bindReadSurface((ogles_context_t*)d->ctx);
        }
    }

    return EGL_TRUE;
}
  1. eglSwapBuffers之后
    應(yīng)該是生成了layer供HWC合成,這部分仍在學(xué)習(xí)當(dāng)中

參考資料
Android OpenGL ES(四):關(guān)于EGL
Android 的OpenGL ES與EGL
極客學(xué)院 Android OpenGL ES 開發(fā)教程
騰訊GAD開發(fā)者平臺 - EGL接口解析與理解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末废酷,一起剝皮案震驚了整個(gè)濱河市瘟檩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌澈蟆,老刑警劉巖墨辛,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異趴俘,居然都是意外死亡睹簇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門寥闪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來太惠,“玉大人,你說我怎么就攤上這事疲憋≡湓ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵缚柳,是天一觀的道長埃脏。 經(jīng)常有香客問我,道長秋忙,這世上最難降的妖魔是什么彩掐? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮翰绊,結(jié)果婚禮上佩谷,老公的妹妹穿的比我還像新娘。我一直安慰自己监嗜,他們只是感情好谐檀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著裁奇,像睡著了一般桐猬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刽肠,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天溃肪,我揣著相機(jī)與錄音,去河邊找鬼音五。 笑死惫撰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的躺涝。 我是一名探鬼主播厨钻,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了夯膀?” 一聲冷哼從身側(cè)響起诗充,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诱建,沒想到半個(gè)月后蝴蜓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俺猿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年茎匠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辜荠。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡汽抚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出伯病,到底是詐尸還是另有隱情,我是刑警寧澤否过,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布午笛,位于F島的核電站,受9級特大地震影響苗桂,放射性物質(zhì)發(fā)生泄漏药磺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一煤伟、第九天 我趴在偏房一處隱蔽的房頂上張望癌佩。 院中可真熱鬧,春花似錦便锨、人聲如沸围辙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姚建。三九已至,卻和暖如春吱殉,著一層夾襖步出監(jiān)牢的瞬間掸冤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工友雳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稿湿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓押赊,卻偏偏與公主長得像饺藤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 本篇文章是基于谷歌有關(guān)Graphic的一篇概覽文章的翻譯:http://source.android.com/de...
    lee_3do閱讀 7,097評論 2 21
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評論 25 707
  • 1、人是軟弱的咽袜,所以要覺知丸卷,讓自己定下來。問題在自己處询刹,不在別人谜嫉。 ——素黑《好好愛自己》 2、有這樣一些人凹联,他...
    喵月嗅雪閱讀 477評論 0 2
  • “姐沐兰,我今天特別感動,不不不蔽挠,是能當(dāng)你的妹妹我很幸運(yùn)住闯,因?yàn)槟阋恢币恢卑菸业某羝猓 ?其實(shí)澳淑,今天我是被妹妹感動了...
    是舒格閱讀 364評論 0 4
  • 以前看過筆名特立獨(dú)行的豬寫的《不要讓未來的你討厭現(xiàn)在的自己》比原,就像這種快餐類的雞湯文集,我一般很少看杠巡,看了也就忘了...
    唐森的閱讀筆記閱讀 503評論 1 6