Android图形

#软件环境:ubuntu,aosp12
#硬件环境:x86 PC

1 介绍

    1. 介绍一些Android图形绘制方法,如基于APP绘制,基于surfaceflinger绘制,基于openGL绘制,基于libdrm绘制
    1. 介绍Android图形绘制原理,APP->surfaceFlinger->hwcomposer过程
    1. 介绍一些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;
}
#基于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

参考:https://www.androidperformance.com/2019/11/06/Android-Systrace-MainThread-And-RenderThread/#/%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0%E7%9B%AE%E5%BD%95

3.2 BufferQueue

3.3 SurfaceFlinger

SurfaceFlinger 最主要的功能:SurfaceFlinger 接受来自多个来源的数据缓冲区,对它们进行合成,然后发送到显示设备。

3.4 Hwcomposer

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值