1. 概覽
EGL是介于各種粉刷(rendering)API如(OpenGL,OpenVG等)和底層視窗系統平台之間的接口。EGL提供各種機制建立圖形context和粉刷surface供客戶API使用。同時,EGL也在繪圖的過程中為本地繪圖平台和客戶api提供同步機制。EGL提供遠端和間接粉刷機制,而GLX API則有這個機制。
2. EGL操作
2.1本地視窗系統和粉刷API
EGL可以在多個作業系統(塞班/嵌入式linux/unix/windows等)和多種本地視窗(X/MicrosoftWindows)中實作。EGL的實作也可能允許本地其他的粉刷api來粉刷EGL surface,如(Xlib,GDI)。
2.1.1 常數類型
1.EGLBoolean:egl的boolean類型,值可以是EGL_TRUE(1) 和 EGL_FALSE (0).
2.EGLint:類似于int類型。
2.1.2 Display
大部分EGL調用都會使用EGLDisplay參數,它代表一個抽象的螢幕。
2.2粉刷上下文和繪圖平面(Rendering Contexts andDrawing Surfaces)
EGL的一個最主要的目的就是提供粉刷上下文和繪圖平面的建立函數供用戶端API使用。EGL定義了多種繪圖平面類型,統稱EGLSurface。主要包括如下三類:
(1)windowsurface:可以将裡面的圖形緩沖畫到螢幕上。
(2)pbufferssurface:資料存在記憶體緩沖上,不能畫在螢幕上。
(3)pixmaps,surface:本地api可以通路的記憶體資料緩沖。
EGLSurface是依照各自的EGLConfig來進行的(其實就是建立EGLSurface的函數需要EGLCongif做參數)。EGLConfig描述了所建立的平面需要的顔色深度,類型,輔助緩沖等一些資訊。
輔助緩存是對應于EGLSurface的,而不是context。如果很多context向同一個surface畫圖,則context之間會共享這些緩沖。Surface和Context之間有一種相容性的說法,滿足相容性條件後,surface才能被context使用。這些條件是:
(1)支援相同類型的顔色緩沖。(顔色緩沖類型包括RGB/luminance等)
(2)具有相同的顔色緩沖深度和輔助緩沖深度。這裡的深度隻各個顔色深度都要相同,比如RGB565與RGB4444中,雖然顔色深度總和都是16bit/pixel,但是每個次元的深度不一樣。是以,他們是不相容的。輔助緩沖有一個特例,如果某個輔助緩沖對于某個客戶API是沒有意義的(不需要的),那麼,這種緩沖不考慮相容性。如,一個surface包含顔色緩沖和stencilbuffer,當OpenVG 粉刷api下的Context包含相同的顔色緩沖時,他們是相容的。因為,OpenVG不需要stencil buffer。
(3)surface和context需要在相同類型的客戶api(都是opengl或都是openVG等)建立函數下建立。
(4)他們的建立函數中使用的display參數是一樣的。
滿足相容條件時,一個context可以往多個EGLSurface上作畫,一個EGLSurface也可以對應多個context。
2.2.1 使用粉刷上下文(Rendering Context)
OpenGL ES定義了用戶端狀态和服務端狀态。是以,OpenGLES的context包含客戶和服務端兩個狀态。OpenVG則沒有。OpenGL ES和OpenVG客戶API都采用了隐含的context作為粉刷入口點,而不是在繪圖函數中傳入Context參數。是以,EGL會提供一個函數(makeCurrent(…))來使某個context變成目前使用狀态。每個線程最多可以為每個支援的用戶端api(opengl/openVG等)建立一個目前粉刷context。另外,同一時刻,一個context隻能被一個線程置成目前。
2.2.2 粉刷模式
EGL支援兩種粉刷模式:後備緩沖和單緩沖。(back buffered and single buffered)
後備緩沖可以用在window和pbuffer兩種surface中,EGL負責相關的記憶體申請和使用。單緩沖則用在pixmapsurface中,其記憶體格式和本地系統使用的pixmap格式一樣,可供本地視窗系統函數通路。當然,某些些客戶api比如Opengl 和OpenVG,也支援單緩沖的windowsurface。
不管是單緩沖還是後備緩沖的surface都可以通過eglCopyBuffers()函數,拷貝到指定的本地pixmap中。
EGL surface對應的本地視窗縮放時,EGL的window surface也需要跟着縮放。一般的實作過程是,本地作業系統和視窗系統執行一個的回調函數通知EGL改變視窗大小,這個改變對用戶端api是透明的。也有一些EGL實作,是通過surface大小改變的函數調用來實作。對于沒有實作視窗改變功能的EGL實作,需要通過調用eglSwapBuffers函數調用來回本地視窗改變。
2.4狀态共享
大部分用戶端api的context狀态是很小的。但是,一些有時候我們希望context之間可以共享一些狀态,省得各個context都擁有一些相同的内部狀态資料。隻有相同客戶api建立(如都是OpenGL建立的)的context才能共享内部一些狀态。
OpenGLcontexts 可以共享texture objects, shader和programobjects, display list objects, pixel和 vertex bufferobjects.
OpenGLES contexts 可以共享texture objects, shader 和program objects, vertex buffer objects.
OpenVG contexts 可以共享images,paint objects, paths.
2.5多線程
EGL和它的用戶端api函數必須是線程安全的。用戶端api和本地繪圖api可以通過一些同步原語來實作同步。
3. EGL函數與錯誤
3.1錯誤
要檢測目前egl調用的詳細錯誤資訊,可以調用:EGLint eglGetError(void);
3.2初始化
(1)EGLDisplayeglGetDisplay(EGLNativeDisplayType display_id);
需要先初始化Display後,才能調用EGL其他函數和用戶端API函數。這裡EGLNativeDisplayType是依不同本地平台而不同的。如,X windows視窗系統下,它對應于XDisplay;對于微軟系統下,它對應于Windows Device Context。
(2)EGLBoolean eglInitialize(EGLDisplaydpy, EGLint *major, EGLint *minor);初始化剛才得到的display。
(3)EGLBoolean eglTerminate(EGLDisplaydpy););釋放剛才得到的display。
3.3EGL資訊
(1)const char *eglQueryString(EGLDisplaydpy,EGLint name);查詢目前display下的EGL資訊。name參數可以是如下幾個:EGL_CLIENT_APIS, EGL_EXTENSIONS, EGL_VENDOR,或者EGL_VERSION.傳回值為查詢結果。
3.4EGL Configuration管理
EGLConfig描述了一個EGLSurface所包含的像數格式,類型,顔色緩沖大小,輔助緩存大小等資訊。如果EGLSurface是屬于windowsurface,那麼這個surface的EGLConfig還包含相關的本地視窗類型。表3-1描述了EGLConfig的屬性值,他們可以作為eglChooseConfig的參數。EGL_CONFIG_ID是一個唯一指定不同EGLConfig的整數值。他們是『1---N』的正整數。

(1)EGLBoolean eglGetConfigs(EGLDisplaydpy, EGLConfig *configs, EGLint config_size,EGLint *num_config);
查詢所有指定display下的EGLCongifs,num_config傳回了可用的數目。
(2)EGLBoolean eglChooseConfig(EGLDisplaydpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint*num_config);傳入需求的屬性清單,看是否有合适的config。
(3)EGLBoolean eglGetConfigAttrib(EGLDisplaydpy, EGLConfig config, EGLint attribute, EGLint *value);查詢某個config的某些屬性值。
3.5粉刷表面(Rendering Surface)
(1)EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
const EGLint *attrib_list);建立windowsurface。
(2)EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, constEGLint *attrib_list);建立pbuffer surface.
(3)EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBufferbuffer, EGLConfig config, const EGLint *attrib_list);綁定surface到用戶端api的buffer裡。
(4)EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,EGLNativePixmapType pixmap, const EGLint *attrib_list);建立nativepixmap粉刷surface。
(5)EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface);銷毀surface。
(6)EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLintattribute, EGLint value);設定surface的屬性值。
(7)EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLintattribute, EGLint *value);查詢surface的屬性值。
相關屬性值見下表:
3.6粉刷紋理(Rendering to Textures)
使用如下一些api可以實作把pbuffersurface裡面像數資料粉刷到OpenGL ES紋理(texture)中。
(1)EGLBoolean eglBindTexImage(EGLDisplaydpy, EGLSurface surface, EGLint buffer);這個指令定義了一個兩維的紋理圖像。紋理圖像包含了指定圖像的buffer緩沖區。目前,EGL隻支援EGL_BACK_BUFFER。也就是說,函數中,buffer隻能等于EGL_BACK_BUFFER。
(2)EGLBooleaneglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);釋放被texture使用的surface緩沖。
3.7粉刷上下文(Rendering Context)
(1)EGLBoolean eglBindAPI(EGLenum api);綁定用戶端api,參數可以是:EGL_OPENGL_API,
EGL_OPENGL_ES_API,或者 EGL_OPENVG_API。
(2)EGLenum eglQueryAPI(void);查詢目前支援的用戶端api。
(3)EGLContexteglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, constEGLint *attrib_list);建立context。
(4)EGLBooleaneglDestroyContext(EGLDisplay dpy, EGLContext ctx);銷毀一個context
(5)EGLBoolean eglMakeCurrent(EGLDisplaydpy, EGLSurface draw, EGLSurface read, EGLContext ctx);這個函數就是前面所說的makecurrent功能。指定目前使用的context,之後的一些api調用都是基于這個context狀态下的。draw參數指定的surface可以用來做所有的操作除了讀像數,read則是用來讀的。read和draw可以指定同一個surface,這樣該surface可以用來讀,也可以寫。
(6)EGLContexteglGetCurrentContext(void); 傳回目前用戶端api的目前context。
(7)EGLSurfaceeglGetCurrentSurface(EGLint readdraw);傳回read/draw的surface。
(8)EGLDisplayeglGetCurrentDisplay(void);傳回目前display。
(9)EGLBoolean eglQueryContext(EGLDisplaydpy, EGLContext ctx, EGLint attribute, EGLint *value);
擷取目前context的屬性值。
3.8同步原語
(1)EGLBoolean eglWaitClient(void);
(2)EGLBoolean eglWaitGL(void);
(3)EGLBoolean eglWaitNative(EGLintengine);
3.9送出顔色緩沖
(1)EGLBoolean eglSwapBuffers(EGLDisplaydpy, GLSurface surface);如果是後備緩沖的window surface,那麼它的顔色緩沖就會被拷貝到本地視窗,如果是單緩沖的surface,那麼這個函數就沒有用了。
(2)EGLBoolean eglCopyBuffers(EGLDisplaydpy, EGLSurface surface, EGLNativePixmapType target);拷貝surface的顔色緩沖到本地pixmap中。
關于送出,如果函數中display和surface參數是目前線程的current context的display和surface,那麼eglSwapBuffers和eglCopyBuffers會在目前的context下執行一個顯式的flush操作(對于opengl或者opengl es是glFlush函數,對于OpenVG則是vgFlush函數)。後來的用戶端api指令也可以馬上發送,但是在這次送出操作完成前(flush),不會被執行。
(3)EGLBoolean eglSwapInterval(EGLDisplaydpy, EGLint interval);用于指定最小的幀發送間隔(一般指video)。
3.10擷取擴充函數指針
void (*eglGetProcAddress(const char *procname))(void);
3.11釋放線程狀态
EGLBoolean eglReleaseThread(void);EGL儲存一些線程狀态供類似elgGetError等函數查詢,調用這個函數可以使他們恢複到初始狀态。