天天看點

Android中opengles,egl庫的結構egl,opengl es的軟硬體實作

目錄

egl,opengl es的軟硬體實作

需要的庫

庫的分工

加載子產品

軟體實作子產品

硬體實作子產品

egl,opengl es的軟硬體實作

需要的庫

//算是android中的egl庫,用來加載具體的實作(軟體實作或者硬體實作)

system\lib\libEGL.so

//opengl具體實作的wrapper,無論軟體硬體實作時,均需加載這2個調用轉發庫



 system\lib\libGLESv1_CM.so  // opengl es 1.0調用的wrapper殼,對應的源檔案是:                                                              

///frameworks/native/opengl/libs/GLES_CM/gl.cpp

system\lib\libGLESv2.so      // opengl es 2.0調用的wrapper殼,可shader程式設計, 對應的源檔案是:

//opengl軟體實作,即agl,包括egl和gl的實作,不分opengl es 1.0和2.0

system\lib\egl\libGLES_android.so



//opengl的硬體實作,例如高通的實作

system\vendor\lib\egl\libEGL_adreno.so

//opengl硬體實作

system\vendor\lib\egl\libGLESv1_CM_adreno.so

system\vendor\lib\egl\libGLESv2_adreno.so
           

以上無論軟體還是硬體具體實作的接口是 EGL/egl.h,GLES/gl.h。

庫的分工

Egl和gl的标準在/frameworks/native/opengl/include/下,通常如下加入标準:

include <EGL/egl.h>

include <GLES/gl.h>
           

加載子產品

這倆标準的實作一個是軟體實作,一個硬體實作,無論軟硬,都需要一個加載子產品。在/frameworks/native/opengl/libs/Android.mk檔案裡的libEGL子產品便是。

23LOCAL_SRC_FILES:= 	       \
24	EGL/egl_tls.cpp        \
25	EGL/egl_cache.cpp      \
26	EGL/egl_display.cpp    \
27	EGL/egl_object.cpp     \
28	EGL/egl.cpp 	       \
29	EGL/eglApi.cpp 	       \   ,
30	EGL/trace.cpp              \
31	EGL/getProcAddress.cpp.arm \
32	EGL/Loader.cpp 	       \

37LOCAL_MODULE:= libEGL
           

當開始使用libEGL 子產品中的egl接口(eglApi.cpp中的某些函數,他們是eglGetDisplay,eglGetProcAddress,eglBindAPI等,他們包含了egl_init_drivers()函數用來初始化子產品的加載,它是實作在egl.cpp中,而且eglApi.cpp是egl接口實作,它是軟體實作的第一層調用)時,就會觸發軟硬體實作子產品的加載,加載軟體實作還硬體實作,在4.3版本中的判斷是:

153    FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
154    if (cfg == NULL) {//說明軟體子產品
155        // default config
156        ALOGD("egl.cfg not found, using default config");
157        mDriverTag.setTo("android");//說明軟體子產品
158    } else {//硬體子產品
159        while (fgets(line, 256, cfg)) {
160            int dpy, impl;
161            if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
162                //ALOGD(">>> %u %u %s", dpy, impl, tag);
163                // We only load the h/w accelerated implementation
164                if (tag != String8("android")) {
165                    mDriverTag = tag;
166                }
167            }
168        }
169        fclose(cfg);
170    }
           

其中EGL/eglApi.cpp 實作了egl接口,這裡的是egl接口的第一層調用,最終調用的是軟硬體實作裡面的egl實作,為什麼?Loader.cpp加載libGLES_android.so或者加載其他opengl廠商實作的so包的時候,有如下一段代碼:

void *Loader::load_driver(const char* kind, const char *tag,
282        egl_connection_t* cnx, uint32_t mask)
……
	egl_t* egl = &cnx->egl;//加載實作包裡的egl接口實作到此處。
342        __eglMustCastToProperFunctionPointerType* curr =
343            (__eglMustCastToProperFunctionPointerType*)egl;
344        char const * const * api = egl_names;
345        while (*api) {
346            char const * name = *api;
347            __eglMustCastToProperFunctionPointerType f =
348                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
349            if (f == NULL) {
350                // couldn't find the entry-point, use eglGetProcAddress()
351                f = getProcAddress(name);
352                if (f == NULL) {
353                    f = (__eglMustCastToProperFunctionPointerType)0;
354                }
355            }
356            *curr++ = f;
357            api++;
358        }

//看一下egl_connection_t結構:
34struct egl_connection_t {
35    enum {
36        GLESv1_INDEX = 0,
37        GLESv2_INDEX = 1
38    };
39
40    inline egl_connection_t() : dso(0) { }
41    void *              dso;
42    gl_hooks_t *        hooks[2];//gl1,gl2接口函數實作加載到此處
43    EGLint              major;
44    EGLint              minor;
45    egl_t               egl;//軟硬體實作的egl接口函數加載到此處
46
47    void*               libGles1;
48    void*               libGles2;
49};

//在看一下其中的egl_t,gl_hooks_t結構:
71struct egl_t {
72    #include "EGL/egl_entries.in",//一系列egl接口中的函數指針變量,待實作庫來填充
73};
74
75struct gl_hooks_t {
76    struct gl_t {
77        #include "entries.in"//,一系列gl接口中函數指針變量,待實作庫來填充
78    } gl;
79    struct gl_ext_t {
80        __eglMustCastToProperFunctionPointerType extensions[MAX_NUMBER_OF_GL_EXTENSIONS];
81    } ext;
82};

           

總結,無論是SF子產品,還是Bootanimation子產品,他們在使用egl的時候,首先找到eglApi.cpp的第一層調用,然後再:例如:

344EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
345        EGLint attribute, EGLint *value)
346{
347    clearError();
348
349    egl_connection_t* cnx = NULL;
350    const egl_display_ptr dp = validate_display_connection(dpy, cnx);
351    if (!dp) return EGL_FALSE;
352
353    return cnx->egl.eglGetConfigAttrib(//!
354            dp->disp.dpy, config, attribute, value);
355}	
           

         至于gl的調用邏輯,在調用egl_init_drivers()函數用來初始化子產品的加載的時候,也把軟硬家的gl實作加載到了一個地方。

361    if (mask & GLESv1_CM) {
362        init_api(dso, gl_names,
363            (__eglMustCastToProperFunctionPointerType*)
364                &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
365            getProcAddress);
366    }
367
368    if (mask & GLESv2) {
369      init_api(dso, gl_names,
370            (__eglMustCastToProperFunctionPointerType*)
371                &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
372            getProcAddress);
373    }
           

         就是egl_connection_t的hooks成員中。

         那麼egl_connection_t又在哪裡存儲呢?libEGL 子產品的egl_context_t裡。當我們eglcreateContext後,我們會把建立的eglcontext中的egl_connection_t的hooks存儲線上程相關的tls中,當調用的gl函數的時候,就從目前線程的tls裡取出hooks來,然後再調用相關gl函數。它的存儲過程是在eglMakeCurrent函數中:

581EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
582                            EGLSurface read, EGLContext ctx)
583{
……
613    // these are our objects structs passed in
614    egl_context_t       * c = NULL;
……
621    if (ctx != EGL_NO_CONTEXT) {
622        c = get_context(ctx);
623        impl_ctx = c->context;
624    } else {
……
650    EGLBoolean result = dp->makeCurrent(c, cur_c,
651            draw, read, ctx,
652            impl_draw, impl_read, impl_ctx);
653
654    if (result == EGL_TRUE) {
655        if (c) {
656            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);//!
……
}
           

libGLESv1_CM.so和libGLESv2.so他們其實是對gl接口的第一層實作,他們轉發調用了目前線程裡的hooks裡相關的實作。

         看一下gl2接口的調用邏輯,:

// /frameworks/native/opengl/libs/GLES2/gl2.cpp 
109    #define API_ENTRY(_api) _api
110
111    #define CALL_GL_API(_api, ...)                                       \
112        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \  //!
113        _c->_api(__VA_ARGS__);
114
115    #define CALL_GL_API_RETURN(_api, ...)                                \
116        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
117        return _c->_api(__VA_ARGS__)
……
122extern "C" {
123#include "gl3_api.in"
124#include "gl2ext_api.in"
125#include "gl3ext_api.in"
126}

// /frameworks/native/opengl/libs/GLES2/gl3_api.in :
1void API_ENTRY(glActiveTexture)(GLenum texture) {
2    CALL_GL_API(glActiveTexture, texture);
3}
4void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) {
5    CALL_GL_API(glAttachShader, program, shader);
6}
7void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const GLchar* name) {
8    CALL_GL_API(glBindAttribLocation, program, index, name);
9}
…….


//	最後看一下關于hooks的本地線程存儲:
368void setGlThreadSpecific(gl_hooks_t const *value) {
369    pthread_setspecific(gGLWrapperKey, value);
370}
371
372gl_hooks_t const* getGlThreadSpecific() {
373    gl_hooks_t const* hooks =  static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey));
374    if (hooks) return hooks;
375    return &gHooksNoContext;
376}
           

         總結,無論是SF子產品,還是Bootanimation子產品,他們在使用gl接口的時候,先去找libGLESv1_CM.so和libGLESv2.so的第一層實作,然後再轉發軟體或硬體實作。

軟體實作子產品

這倆标準的agl軟體實作在/frameworks/native/opengl/libagl/下,觀其部分mk檔案:

9LOCAL_SRC_FILES:= \
10	egl.cpp                     \  //egl的實作,其餘是gl的實作
11	state.cpp		            \
12	texture.cpp		            \
13    Tokenizer.cpp               \
14    TokenManager.cpp            \
15    TextureObjectManager.cpp    \
16    BufferObjectManager.cpp     \
17	array.cpp.arm		        \
18	fp.cpp.arm		            \
19	light.cpp.arm		        \
20	matrix.cpp.arm		        \
21	mipmap.cpp.arm		        \
22	primitives.cpp.arm	        \
23	vertex.cpp.arm
……
29LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils liblog libpixelflinger libETC1 libui
30LOCAL_LDLIBS := -lpthread -ldl
31
32ifeq ($(TARGET_ARCH),arm)
33	LOCAL_SRC_FILES += fixed_asm.S iterators.S
34	LOCAL_CFLAGS += -fstrict-aliasing
35endif

……

44# we need to access the private Bionic header <bionic_tls.h>
45LOCAL_C_INCLUDES += bionic/libc/private

……

48LOCAL_MODULE:= libGLES_android
49
50include $(BUILD_SHARED_LIBRARY)
           

硬體實作子產品

硬體的實作包括在/frameworks/native/opengl/libs/Android.mk檔案裡:

Egl實作:例如高通的\libEGL_adreno.so

Gl實作:system\vendor\lib\egl\libGLESv1_CM_adreno.so,system\vendor\lib\egl\libGLESv2_adreno.so

圖示:

Android中opengles,egl庫的結構egl,opengl es的軟硬體實作

轉載請注明。