OpenGL ES
与EGL
OpenGL
一般OpenGL
被认为是一个API
(Application Programming Interface, 应用程序编程接口),包含了一系列可以操作图形、图像的函数。然而,OpenGL
本身并不是一个API,它仅仅是一个由Khronos
组织制定并维护的规范(Specification)。
OpenGL规范
严格规定了每个函数该如何执行,以及它们的输出值。至于内部具体每个函数是如何实现的,将由OpenGL
库的开发者自行决定
实际的OpenGL
库的开发者通常是显卡的生产商
OpenGL ES(OpenGL for Embedded Systems)
是从OpenGL
裁剪的定制而来的,去除了一些复杂图元等许多非绝对必要的特性
OpenGL
还是很值得学习的,大家可以参考:LearnOpenGL教程的中文翻译
EGL
我们知道OpenGL ES
定义了一个渲染图形的API
,但没有定义窗口系统。
为了让OpenGL ES
能够适合各种平台,OpenGL ES
需要与一个知道如何通过操作系统创建和访问窗口的库结合使用
在Android
中的这个库就是EGL
。(没有什么问题是不能通过增加一个中间层来解决的,有的话那就再增加一个。。。。。)
整体结构如下(网上盗图):
EGL
的用法
使用EGL
绘制的一般步骤如下:
- 获取 EGL Display 对象:eglGetDisplay()
- 初始化与 EGLDisplay 之间的连接:eglInitialize()
- 获取 EGLConfig 对象:eglChooseConfig()
- 创建 EGLContext 实例:eglCreateContext()
- 创建 EGLSurface 实例:eglCreateWindowSurface()
- 连接 EGLContext 和 EGLSurface:eglMakeCurrent()
- 使用 OpenGL ES API 绘制图形:gl_*()
- 切换 front buffer 和 back buffer 送显:eglSwapBuffer()
- 断开并释放与 EGLSurface 关联的 EGLContext 对象:eglRelease()
- 删除 EGLSurface 对象
- 删除 EGLContext 对象
- 终止与 EGLDisplay 之间的连接
Android
中的封装
前面的章节我们介绍过,无论开发者使用什么渲染API,一切内容都会渲染到Surface
上
- 此处的
Surface
指的是framework/native/libs/gui/Surface.cpp
对应的业务逻辑
当SurfaceFlinger
以消费者的角色获取到显示数据后,会开始进行渲染操作,在过程中也存在一个Surface
- 定义在
framework/native/services/surfaceflinger/RenderEngine/Surface.cpp
-
Surface::Surface(const RenderEngine& engine)
-
mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
…
}
Surface::~Surface() {
setNativeWindow(nullptr);
}
void Surface::setNativeWindow(ANativeWindow* window) {
…
if (mWindow) {
mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
}
}
void Surface::swapBuffers() const {
if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
…
}
}
EGLint Surface::queryConfig(EGLint attrib) const {
EGLint value;
if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
value = 0;
}
return value;
}
EGLint Surface::querySurface(EGLint attrib) const {
EGLint value;
if (!eglQuerySurface(mEGLDisplay, mEGLSurface, attrib, &value)) {
value = 0;
}
return value;
}
接口定义结合上面EGL
的知识应该很容易理解,下面我们开始SurfaceFlinger
学习吧
SurfaceFlinger
的启动过程
从Android 4.4
开始SurfaceFlinger
服务运行在一个独立的守护进程中(以前在SystemServer
中),这样系统的图像绘制性能会得到一定的提升。frameworks/native/services/surfaceflinger/surfaceflinger.rc
中关于SurfaceFlinger
的定义如下:
service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
onrestart restart zygote
…
可以看到surfaceflinger
放到了core
组里,这个组的服务会在系统初始化时启动。SurfaceFlinger
启动的入口函数main()
代码如下:
int main(int, char**) {
…
// 启动 Gralloc 服务
startGraphicsAllocatorService();
// 设置当前Binder服务可连接最大线程数
ProcessState::self()->setThreadPoolMaxThreadCount(4);
// 通过 startThreadPool 通知 Binder 驱动当前线程已准备完成
sp ps(ProcessState::self());
ps->startThreadPool();
// 初始化 SurfaceFlinger
sp flinger = new SurfaceFlinger();
// 调整进程优先级为 PRIORITY_URGENT_DISPLAY
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
// 调整调度策略,将其设置为前台进程
// 这两种标志涉及了内核的 完全公平调度算法,感兴趣的同学可以百度一下
// 在这里的目的是保证 SurfaceFlinger 的较高优先级,方便快速响应更新图像的请求
set_sched_policy(0, SP_FOREGROUND);
…
// 注册 Service 前的初始化部分
flinger->init();
// 注册 SurfaceFlinger 服务
sp sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
// 注册 GpuService 服务
sp gpuservice = new GpuService();
sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
// 启动 DisplayService 服务
startDisplayService(); // dependency on SF getting registered above
…
// run surface flinger in this thread
flinger->run();
return 0;
}
main()
方法中注释比较详细就不细说了,方法总结下来有三点:
- 初始化
GraphicsAllocatorService
、DisplayService
和GpuService
服务 set_sched_policy
和sched_setscheduler
设置进程优先级SurfaceFlinger
对象的初始化以及init
和run
方法的调用
SurfaceFlinger
的初始化过程设计的模块比较多,我们先简单看下类关系图:
SurfaceFlinger
对象初始化
SurfaceFlinger
的类定义如下:
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
private IBinder::DeathRecipient,
private HWC2::ComposerCallback
{}
BnSurfaceComposer
类:类图中该类实现的是ISurfaceComposer
接口,而ISurfaceComposer
又是一套定义好的Binder
类Binder
篇提到过,当出现Bn*
开头的类就可以把它看做Binder服务类
了,所以SurfaceFlinger
这里是作为一个Binder
服务对象- 上一篇在
SurfaceSession
初始化时,SurfaceComposerClient
对象就是通过ServiceManager
获取了SurfaceFlinger
服务 - 然后通过服务提供的
createConnection()
方法获取了ISurfaceComposerClient
对象,也就是上面类图中提到的Client
类 HWC2::ComposerCallback
类:面向底层硬件状态的监听回调接口,包括onHotplugReceived
,显示屏热插拔事件回调onRefresh