#软件环境:ubuntu,aosp12
#硬件环境:x86 PC
1 介绍
-
- 介绍一些Android图形绘制方法,如基于APP绘制,基于surfaceflinger绘制,基于openGL绘制,基于libdrm绘制
-
- 介绍Android图形绘制原理,APP->surfaceFlinger->hwcomposer过程
-
- 介绍一些layer相关:layer管理,layer截屏,layer合成
2 Android OpenGL ES
使用GPU渲染一副图像,需要将好几种不同类型的buffer都传给它,这些buffer包括Command Buffer (绘图指令)、Vertex Buffer(顶点数据)、Texture Buffer(纹理数据,即图片)、Framebuffer(GPU最终输出的结果)等等。
为了兼容Android,设备需要提供适用于EGL、OpenGL ES 1.x 和 OpenGL ES 2.0的驱动程序,可以选择支持OpenGL ES 3.x.
源码:frameworks\base\opengl\libs
Lib库:libEGL, libGLESv1_CM.so, libGLESv2.so
2.1 libEGL
-
frameworks/native/opengl/libs/EGL/ -> /system/lib/libEGL.so
-
EGL是用来管理绘图表面的(Drawing surfaces),是Android使用OpenGL ES API绘图的助手
(1)与本地窗口系统进行通信
(2)查找绘图表面可用的类型和配置信息
(3)创建绘图表面
(4)同步OpenGL ES 2.0和其他的渲染API(Open VG、本地窗口系统的绘图命令等)
(5)管理渲染资源,比如材质 -
EGL 和 OpenGL ES API的联系
(1)通过解析OpenGL ES API函数库 libGLES_xx.so来获取函数指针,进行调用。
(2)通过线程局部存储机制进行联系 -
加载openGLES实现
libEGL加载OpenGL ES驱动,首选路径/vendor/lib/egl或/vendor/lib64/egl, 根据系统属性:ro.hardware.egl 和 ro.board.platform来寻找库名
$adb -s 0.0.0.0:6520 shell getprop ro.hardware.egl
mesa
$adb -s 0.0.0.0:6520 shell getprop ro.board.platform
vsoc_x86
D libEGL : loaded /vendor/lib/egl/libGLES_mesa.so
W EGL-MAIN: Failed to open any DRM device
W libEGL : eglInitialize(0xe9e83cb0) failed (EGL_NOT_INITIALIZED)
2.2 libGLESv1/2_CM
libGLESv1_CM.so,libGLESv2.so都是一个简单的wrapper,对OpenGLES API的封装,
其中libGLESv1_CM.so是对OpenGLES1.0库的封装,libGLESV2.so是对OpenGLES2.0库的封装。
这两个库封装的对像是OpenGLES API的实现,硬件OpenGLES API的实现一般会编译成库,
例如GPU Vivante厂商的OpenGLES1.0的API库一般就命名为libGLESv1_CM_VIVANTE.so,OpenGLES2.0的一般命名为libGLESv2_VIVANTE.so
3图形绘制
3.1 Android基于SurfaceFlinger绘制
参考Android12(S)图形博客:https://www.cnblogs.com/roger-yu/p/15707940.html
- 使用方法
#下载代码放到android源码目录下;
git clone https://github.com/yrzroger/NativeSFDemo.git externel/
#执行mm编译获得可执行档NativeSFDemo
m NativeSFDemo
adb push NativeSFDemo /system/bin/
#运行程序
adb shell NativeSFDemo
- 效果展示
红色->蓝色->绿色背景交替展示
- 绘制到指定屏
参考main_multi_display branch
2.3 Android基于OpenGLES绘制
- SurfaceFlinger/BootAnimation或其他demo,都是基于EGL和openGL ES进行绘制,其步骤如下
1调用EGL初始化环境
eglGetDisplay
egl_init_drivers #找到EGL和OpenGL ES厂商实现,对这些函数进行赋值
eglInitialize
eglCreateWindowSurface
eglCreateContext
eglMakeCurrent
2有了surface,可以使用opengl绘制了
create_texture
glGenTextures
Rendor
glDrawElements
eglSurfaceAttrib
3绘制完SwapBuffer,触发queueBuffer和dequeueBuffer,图画就一副一副画出来
eglSwapBuffers
- bootanimation。绘制开机静态图片流程
bool BootAnimation::android() {
glActiveTexture(GL_TEXTURE0); //激活纹理单元(初始化为GL_TEXTURE0)
SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); //将png初始化到Texture 结构mAndroid中
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
mCallbacks->init({});
// clear screen
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
glUseProgram(mImageShader); //使用mImageShader作为当前渲染状态的一部分,mImageShader链接image着色器
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(mDisplay, mSurface);
// Blend state
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //源和目标颜色混合
const nsecs_t startTime = systemTime();
do {
processDisplayEvents();
const GLint xc = (mWidth - mAndroid[0].w) / 2;
const GLint yc = (mHeight - mAndroid[0].h) / 2;
const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
updateRect.height()); //定义裁剪框
nsecs_t now = systemTime();
double time = now - startTime;
float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
GLint x = xc - offset;
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); //绑定2D纹理目标
drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h);
drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h);
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); //绑定2D纹理目标
drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h);
EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
if (res == EGL_FALSE)
break;
// 12fps: don't animate too fast to preserve CPU
const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
if (sleepTime > 0)
usleep(sleepTime);
checkExit(); //检查是否有退出标志
} while (!exitPending());
glDeleteTextures(1, &mAndroid[0].name);
glDeleteTextures(1, &mAndroid[1].name);
return false;
}
- test-opengl-gl_basic. frameworks/native/opengl/tests/有很多基于openGL绘制的demo
https://android.googlesource.com/platform/frameworks/native/+/master/opengl/tests/EGLTest/
#基于openGL ES和EGL的demo
cd frameworks/native/opengl/tests/gl_basic
mm
adb push out/target/product/trout_x86/testcases/test-opengl-gl_basic/x86/test-opengl-gl_basic /data/nativetest/
adb shell ./data/nativetest/test-opengl-gl_basic
2.4 Android基于libdrm绘制
- drmModePageFlip. 基于VSYNC更新屏幕内容
- drmModeSetPlane. 同步调用更新一个plane
- drmModeAtomicCommit. Android中drm-hwc使用的画面提交方式,异步调用更新多个plane
参考何小龙博客:https://blog.csdn.net/hexiaolong2009/article/details/83720940
3 绘图流程
如上图app图形绘图为例,介绍app ->bufferqueue -> surfaceflinger -> hwcomposer基本流程.
3.1 App
3.2 BufferQueue
3.3 SurfaceFlinger
SurfaceFlinger 最主要的功能:SurfaceFlinger 接受来自多个来源的数据缓冲区,对它们进行合成,然后发送到显示设备。