硬件加速:RenderThread处理DrawOp树

2022-10-09 12:40:32 浏览数 (1)

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;
}

摘一张图:

总结流程

初始化流程

参考文章

android硬件加速

GPU渲染简介

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

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

0 人点赞