Android 图形驱动初始化(二十三),移动开发者升职加薪的8项技能

本文深入解析Android图形驱动初始化过程,包括如何通过EGL库获取Display,介绍图形驱动初始化的关键步骤,涉及EGL、OpenGL ES库的加载和函数表初始化。适合移动开发者提升技术理解。
摘要由CSDN通过智能技术生成

这里通过调用 EGL 库的 eglGetDisplay() 获得 Display。eglGetDisplay() 的定义位于 frameworks/native/opengl/libs/EGL/eglApi.cpp :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

EGLDisplay eglGetDisplay(EGLNativeDisplayType display)

{

clearError();

uintptr_t index = reinterpret_cast<uintptr_t>(display);

if (index >= NUM_DISPLAYS) {

return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);

}

if (egl_init_drivers() == EGL_FALSE) {

return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);

}

EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);

return dpy;

}

在这个函数中,首先根据需要执行 egl_init_drivers() 初始化驱动库。然后通过 egl_display_t::getFromNativeDisplay(display) 获得 Dispaly。

egl_display_t::getFromNativeDisplay(display) 的定义(位于 frameworks/native/opengl/libs/EGL/egl_display.cpp)如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {

Mutex::Autolock _l(lock);

// get our driver loader

Loader& loader(Loader::getInstance());

egl_connection_t* const cnx = &gEGLImpl;

if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {

EGLDisplay dpy = cnx->egl.eglGetDisplay(display);

disp.dpy = dpy;

if (dpy == EGL_NO_DISPLAY) {

loader.close(cnx->dso);

cnx->dso = NULL;

}

}

return EGLDisplay(uintptr_t(display) + 1U);

}

在这个函数中,最为关键的就是,在 disp.dpy 为 EGL_NO_DISPLAY 时,通过 cnx->egl.eglGetDisplay() 初始化它了。

EGLDisplay 的定义如下:

1

typedef void *EGLDisplay;

它仅是 void 指针的 typedef。

总结一下获取 Display 的整个过程

  • 通过 frameworks/native/opengl/libs/EGL 初始化图形驱动;

  • 通过厂商提供的设备特有的 EGL 库接口初始化 Display。

Android 图形驱动初始化

===============

接下来更详细地看一下图形驱动初始化。这通过 egl_init_drivers() 完成,该函数定义 (位于frameworks/native/opengl/libs/EGL/egl.cpp) 如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

egl_connection_t gEGLImpl;

gl_hooks_t gHooks[2];

. . . . . .

static EGLBoolean egl_init_drivers_locked() {

if (sEarlyInitState) {

// initialized by static ctor. should be set here.

return EGL_FALSE;

}

// get our driver loader

Loader& loader(Loader::getInstance());

// dynamically load our EGL implementation

egl_connection_t* cnx = &gEGLImpl;

if (cnx->dso == 0) {

cnx->hooks[egl_connection_t::GLESv1_INDEX] =

&gHooks[egl_connection_t::GLESv1_INDEX];

cnx->hooks[egl_connection_t::GLESv2_INDEX] =

&gHooks[egl_connection_t::GLESv2_INDEX];

cnx->dso = loader.open(cnx);

}

return cnx->dso ? EGL_TRUE : EGL_FALSE;

}

static pthread_mutex_t sInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;

EGLBoolean egl_init_drivers() {

EGLBoolean res;

pthread_mutex_lock(&sInitDriverMutex);

res = egl_init_drivers_locked();

pthread_mutex_unlock(&sInitDriverMutex);

return res;

}

图形驱动初始化通过 Loader::open(egl_connection_t* cnx) 完成,初始化的结果将存储于全局结构 egl_connection_t gEGLImpl 和 gl_hooks_t gHooks[2] 中。

来看一下 gl_hooks_t 的定义(位于 frameworks/native/opengl/libs/hooks.h):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

// maximum number of GL extensions that can be used simultaneously in

// a given process. this limitation exists because we need to have

// a static function for each extension and currently these static functions

// are generated at compile time.

#define MAX_NUMBER_OF_GL_EXTENSIONS 256

. . . . . .

#undef GL_ENTRY

#undef EGL_ENTRY

#define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);

#define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);

struct egl_t {

#include "EGL/egl_entries.in"

};

struct gl_hooks_t {

struct gl_t {

#include "entries.in"

} gl;

struct gl_ext_t {

__eglMustCastToProperFunctionPointerType extensions[MAX_NUMBER_OF_GL_EXTENSIONS];

} ext;

};

#undef GL_ENTRY

#undef EGL_ENTRY

其中 __eglMustCastToProperFunctionPointerType 定义 (位于frameworks/native/opengl/include/EGL/egl.h) 如下:

1

2

3

4

/* This is a generic function pointer type, whose name indicates it must

* be cast to the proper type *and calling convention* before use.

*/

typedef void (*__eglMustCastToProperFunctionPointerType)(void);

__eglMustCastToProperFunctionPointerType 是函数指针类型。struct gl_hooks_t 的 struct gl_ext_t ext 即为函数指针表,它们用来描述 EGL 扩展接口。

struct gl_hooks_t 内的 struct gl_t 结构体,其结构体成员在另外一个文件,即 entries.in 中定义,该文件位于 frameworks/native/opengl/libs/entries.in

1

2

3

4

5

6

GL_ENTRY(void, glActiveShaderProgram, GLuint pipeline, GLuint program)

GL_ENTRY(void, glActiveShaderProgramEXT, GLuint pipeline, GLuint program)

GL_ENTRY(void, glActiveTexture, GLenum texture)

GL_ENTRY(void, glAlphaFunc, GLenum func, GLfloat ref)

GL_ENTRY(void, glAlphaFuncQCOM, GLenum func, GLclampf ref)

. . . . . .

配合 frameworks/native/opengl/libs/hooks.h 中 GL_ENTRY 宏的定义:

1

#define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);

可以看到 struct gl_hooks_t 的 struct gl_t gl 的所有成员都是函数指针,即它是一个函数表,一个 OpenGL 接口函数的函数表。

上面看到的 struct egl_t 与 struct gl_hooks_t 的 struct gl_t gl 定义类似,只是它的结构体成员来自于另外一个文件 frameworks/native/opengl/libs/EGL/egl_entries.in

1

2

3

4

5

6

EGL_ENTRY(EGLDisplay, eglGetDisplay, NativeDisplayType)

EGL_ENTRY(EGLBoolean, eglInitialize, EGLDisplay, EGLint*, EGLint*)

EGL_ENTRY(EGLBoolean, eglTerminate, EGLDisplay)

EGL_ENTRY(EGLBoolean, eglGetConfigs, EGLDisplay, EGLConfig*, EGLint, EGLint*)

EGL_ENTRY(EGLBoolean, eglChooseConfig, EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)

. . . . . .

EGL_ENTRY 宏的定义与 GL_ENTRY 宏的完全相同。struct egl_t 同样为一个函数表,只是它是 EGL 接口的函数表。

再来看 egl_connection_t 的定义,位于 frameworks/native/opengl/libs/EGL/egldefs.h

1

2

3

4

5

6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值