前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >硬件加速:RenderThread处理DrawOp树

硬件加速:RenderThread处理DrawOp树

作者头像
小柔
发布2022-10-09 12:40:32
5840
发布2022-10-09 12:40:32
举报
文章被收录于专栏:小柔博客园小柔博客园

theme: condensed-night-purple

初始化硬件加速环境

在ViewRootImpl的setView方法中会判断如果支持硬件加速就初始化硬件加速的环境并将创建的HardwareRenderer保存到ViewRootImpl的mAttachInfo中

软件绘制和硬件绘制

代码语言:javascript
复制
 final boolean hardwareAccelerated =
                (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;

    if (hardwareAccelerated) {
           //是否支持开启硬件加速 ,通常都是true
         if (!HardwareRenderer.isAvailable()) {
            return;
          }
           //初始化HardwareRenderer
     mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent);
          if (mAttachInfo.mHardwareRenderer != null) {
          mAttachInfo.mHardwareRenderer.setName(attrs.getTitle().toString());
        mAttachInfo.mHardwareAccelerated =
                    mAttachInfo.mHardwareAccelerationRequested = true;
                }
            }
        }
HardwareRenderer.create主要工作
  • 建立硬件加速环境
  • 创建HardwareRenderer并保存到ViewRootImpl的attachInfo中(后续会通过该属性进行硬件加速的构建环节)
  • 创建RootRenderNode之后的DisplayList要同步到根RenderNode中
  • 为当前widow建立一个ThreadProxy用于向RenderThread提交绘制任务DrawFrameTask(RenderThread中通过Quene来存储这些TASK)
代码语言:javascript
复制
static HardwareRenderer create(Context context, boolean translucent) {
    HardwareRenderer renderer = null;
    if (DisplayListCanvas.isAvailable()) {
        renderer = new ThreadedRenderer(context, translucent);
    }
    return renderer;
}
    
ThreadedRenderer(Context context, boolean translucent) {
    final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
    ...
    <!--建立rootnode-->
    long rootNodePtr = nCreateRootRenderNode();
    mRootNode = RenderNode.adopt(rootNodePtr);
   <!--建立native ThreadProxy-->
    mNativeProxy = nCreateProxy(translucent, rootNodePtr);
    ...
}

ThreadProxy初始化工作: 启动RenderThread并使用mRenderThread属性引用 向RenderThread提交为当前窗口创建CanvasContext的任务,之后的绘制指令会通过它进行中转

RenderThread

代码语言:javascript
复制
RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
, mNextWakeup(LLONG_MAX)
, mDisplayEventReceiver(nullptr)
, mVsyncRequested(false)
, mFrameCallbackTaskPending(false)
, mFrameCallbackTask(nullptr)
, mRenderState(nullptr)
, mEglManager(nullptr) {
Properties::load();
mFrameCallbackTask = new DispatchFrameCallbacks(this);
mLooper = new Looper(false);
run("RenderThread");
}

创建EGLManager(管理EGL Surface,OpenGl上下文),RenderState(渲染状态机),mDisplayEventReceiver(后续接受Vsync事件处理),Looper(用于执行渲染的TASK操作)。由于RenderThread是单例,因此上面这些属性也都是单例的

mDisplayEventReceiver

接收SF上抛的Vsync信号,通过监听DisplayEventReceiver的BitTube来回调编舞者的doFrame方法

代码语言:javascript
复制
void RenderThread::initializeDisplayEventReceiver() {
    mDisplayEventReceiver = new DisplayEventReceiver();
    status_t status = mDisplayEventReceiver->initCheck();
    //监听FD
    mLooper->addFd(mDisplayEventReceiver->getFd(), 0,
            Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this);
}

CanvasContext

也叫作OPENGL的上下文(持有EGLContetx和EGLSurface);在创建RenderThread的时候会向RenderThread发送第一个Task,就是创建CanvasContext

CanvasContext.setSurface

1.创建EGLContext和EGLSurface

2.将当前EGLSurface(本质是ANativeWindow)绑定到EGLContext(有多个EGLSurface的时候控制渲染哪个Surface)

持有mRenderThread,rootRenderNode,mEglManager这些属性

ANativeWindwos其实是EGLSurface在native层的Surface对象,通过eglManager创建

Window持有ViewRootImpl持有attachInfo持有mHardWare---》创建持有ThreadProxy---》ThreadProxy提交创建CanvasContext的申请,CanvasContext中创建EGLContext,EGLSurface并绑定需要渲染的Surface---》持有RenderThread等待Vsync信号

代码语言:javascript
复制
void CanvasContext::setSurface(ANativeWindow* window) {
    mNativeWindow = window;
    //建立EglSurface
    if (window) {
        mEglSurface = mEglManager.createSurface(window);
    }
    if (mEglSurface != EGL_NO_SURFACE) {
        const bool preserveBuffer = (mSwapBehavior != kSwap_discardBuffer);
        mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
        mHaveNewSurface = true;
        //绑定上下文
        makeCurrent();
    }}

EGLSurface EglManager::createSurface(EGLNativeWindowType window) {
    //构建EglContext
    initialize();
    //创建EglSurface
    EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, nullptr);
         return surface;
}

//最后创建egl_window_surface_v2_t,将window当成ANativeWindow
static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
        NativeWindowType window, const EGLint* /*attrib_list*/)
{
   ...
    egl_surface_t* surface;
   //其实返回的就是egl_window_surface_v2_t
    surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
            static_cast<ANativeWindow*>(window));
..	    return surface;
}

摘一张图:

总结流程

初始化流程

image.png
image.png

参考文章

android硬件加速

GPU渲染简介

GPU和CPU的渲染和渲染管道出图原理

Android硬件加速(二)-RenderThread与OpenGLGPU渲染

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • theme: condensed-night-purple
  • 初始化硬件加速环境
    • HardwareRenderer.create主要工作
      • RenderThread
        • mDisplayEventReceiver
      • CanvasContext
        • CanvasContext.setSurface
    • 总结流程
      • 初始化流程
      • 参考文章
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档