Android硬件渲染环境初始化


    硬件渲染是指通过GPU进行渲染,软件渲染是指通过CPU进行渲染。

    在Android中,硬件渲染的过程是通过CPU对需要绘制的内容使用指令进行标记,再通过GPU将标记的指令转换为对应的OpenGL指令进行渲染。从Android4.0开始,UI绘制默认开启硬件加速。在Android5.0之前,Android UI线程和渲染线程是同一个线程,但在Android5.0之后,渲染过程在单独的线程中进行,这个线程就是RenderThread。

一.硬件加速渲染的开启

    在Android中,硬件渲染环境的初始化是从ViewRootImpl的setView方法开始的。

    在ViewRootImpl的setView方法中,主要做了三件事:

1)判断参数中的View是否为RootViewSurfaceTaker。如果为RootViewSurfaceTaker,则调用willYouTakeTheSurface方法,获取SurfaceHolder.Callback2,并保存到mSurfaceHolderCallback中。

2)如果mSurfaceHolderCallback不为空,说明开发者接管了当前Activity的Surface,则创建TakenSurfaceHolder,并保存在mSurfaceHolder中。

3)如果mSurfaceHolder为空,说明开发者没有接管当前Activity的Surface,则调用enableHardwareAcceleration方法开启硬件加速。
0
    当在Activity中调用Window的takeSurface方法接管Activity的Surface后,Activity的渲染会脱离Android的View体系,相当于整个Activity都是SurfaceView。

class TestActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 通过这种方式可以脱离Android View体系,相当于整个Activity都是SurfaceView
        window.takeSurface(object : SurfaceHolder.Callback2 {
            override fun surfaceCreated(holder: SurfaceHolder) {
            }

            override fun surfaceChanged(
                holder: SurfaceHolder,
                format: Int,
                width: Int,
                height: Int
            ) {
            }

            override fun surfaceDestroyed(holder: SurfaceHolder) {
            }

            override fun surfaceRedrawNeeded(holder: SurfaceHolder) {
            }
        })
    }
}

    在ViewRootImpl的enableHardwareAcceleration方法中主要做了三件事:

1)通过ThreadedRenderer的静态方法create创建ThreadedRenderer。

2)将创建的ThreadedRenderer保存到mAttachInfo的mThreadedRenderer字段上。

3)为ThreadedRenderer设置SurfaceControl。
1

1.ThreadedRenderer的初始化

    ThreadedRenderer继承自HardwareRenderer。在ThreadedRenderer的构造方法中,会直接创建ThreadedRenderer并返回。

    在HardwareRenderer的构造方法中,主要做了三件事:

1)创建Native层的RootRenderNode,作为窗口的渲染根节点,并返回对应的地址。

2)将返回的地址封装成Java层的RenderNode。

3)创建Native层的RenderProxy并返回对应的地址,RenderProxy负责从UI线程向Render线程发送渲染指令。
2

2.RenderProxy的创建

    HardwareRenderer的nCreateProxy方法对应的Native实现为android_graphics_HardwareRenderer的android_view_ThreadedRenderer_createProxy函数。

    在android_view_ThreadedRenderer_createProxy函数中,主要做了两件事:

1)获取Native层的RootRenderNode。

2)会创建RenderProxy,RenderProxy负责从UI线程向Render线程发送渲染指令。
3
    在RenderProxy的构造方法中,会创建RenderThread、CanvasContext和DrawFrameTask。

  • RenderThread:负责监听与请求VSync信号,在VSync信号到来时执行任务并请求下一次VSync信号。
  • CanvasContext:负责渲染节点的渲染与渲染管线的管理。
  • DrawFrameTask:负责硬件渲染中每一帧渲染任务的管理,包括布局的测量构建、多层级的管理等。

4

二.RenderProxy中组件的初始化

1.RenderThread的创建

    RenderThread继承自ThreadBase,ThreadBase继承自Thread。

    在RenderThread的getInstance方法中,主要做了两件事:

1)创建RenderThread。

2)并调用RenderThread的start方法启动线程。
5
    在RenderThread的父类ThreadBase的构造方法中,会创建Looper和WorkQueue。Looper用于线程的消息驱动。WorkQueue用于存储RenderThread中执行的任务,WorkQueue中存储的任务类型为WorkItem。
6
    在RenderThread的start方法中,会调用threadLoop方法开始循环执行任务。在RenderThread的threadLoop方法中,主要做了两件事:

1)调用initThreadLocals方法,初始化组件。

2)开启循环,执行任务。
7

2.CanvasContext的创建

    CanvasContext在RenderProxy中创建。RenderProxy将CanvasContext的create方法封装成任务,添加到RenderThread的WorkQueue中等待执行。

    在CanvasContext的create方法中,主要做了两件事:

1)根据指定类型创建对应的渲染管线。

2)创建CanvasContext。
8

3.DrawFrameTask的初始化

    DrawFrameTask在RenderProxy中创建,通过setContext方法初始化。在DrawFrameTask的setContext方法中,会保存CanvasContext、RootRenderNode、RenderThread。
9

三.RenderThread的启动

1.RenderThread中组件的初始化

    在RenderThread的initThreadLocals方法中,主要做了三件事:

1)调用initializeChoreographer方法,初始化VSync信号请求接收组件。

2)创建EglManager,EglManager用在初始化Open GL渲染上下文。

3)创建RenderState,RenderState用于记录渲染状态。
10
    在RenderThread的initializeChoreographer方法中,主要做了三件事:

1)创建AChoreographer。AChoreographer是Native层Choreographer的代理类,AChoreographer是对Choreographer指针的强制转换,当需要调用VSync信号相关的方法时,会将AChoreographer强制转换回Choreographer。两者关系与ACanvas和Canvas类似。Native层Choreographer继承自DisplayEventDispatcher。

2)通过向Looper添加文件描述符的方式的监听VSync信号的分发。

3)创建ChoreographerSource。ChoreographerSource是对AChoreographer的封装,用于在RenderThread中请求与接收VSync信号。ChoreographerSource继承自VSyncSource,VSyncSource定义了请求与处理VSync信号的方法。
11

2.RenderThread中任务的处理

    在RenderThread的threadLoop方法中,当组件初始化完成后,会开while启循环处理任务。在while循环中,主要做了三件事:

1)根据上一次任务队列执行完毕后返回的时间,对线程进行阻塞等待。

2)执行任务队列中的任务,并计算等待时间。

3)处理动画帧任务。
12
    waitForWork方法定义在RenderThread的父类ThreadBase中。在ThreadBase的waitForWork方法中,主要做了三件事:

1)获取队列中下一个待任务任务的开始时间。

2)通过减去当前的时间,计算出线程需要阻塞的时间。

3)阻塞线程开启休眠。
13

3.RenderThread中动画帧的处理

    当外部需要执行动画帧任务时,会调用RenderThread的postFrameCallback方法,在RenderThread的postFrameCallback方法中会对任务进行保存。
14
    在RenderThread的threadLoop方法的循环中,在处理完WorkQueue中的任务后,如果发现有需要处理的动画帧任务,会去处理动画帧任务。

    关于动画帧任务的处理,主要做了四件事:

1)对未分发的VSync信号进行分发,触发动画帧任务的执行。

2)将mPendingRegistrationFrameCallbacks中的动画帧任务转移到mFrameCallbacks中。

3)清空mPendingRegistrationFrameCallbacks。

4)请求下一次的VSync信号。
15
    在ChoreographerSource的drainPendingEvents方法中,会调用AChoreographer_handlePendingEvents函数分发VSync信号。
16

3.1 VSync信号的请求

    在RenderThread的requestVsync方法中,会调用ChoreographerSource的requestNextVsync方法。requestNextVsync方法内部又调用了AChoreographer_postVsyncCallback函数。
17
    在AChoreographer_postVsyncCallback函数中,将AChoreographer转换为Choreographer,并调用Choreographer的postFrameCallbackDelayed方法。
18
    在Choreographer的postFrameCallbackDelayed方法中,主要做了两件事:

1)将回调封装成FrameCallback并保存。

2)请求VSync信号。
19

3.2 VSync信号的分发

    当VSync信号到来时,RenderThread的Looper会从Choreographer的Fd中检测到Looper::EVENT_INPUT消息,并回调RenderThread静态方法的choreographerCallback。

    在RenderThread的静态方法choreographerCallback中,主要做了两件事:

1)获取RenderThread和AChoreographer。

2)调用AChoreographer_handlePendingEvents函数。
20
    在AChoreographer_handlePendingEvents函数中,会调用Choreographer的handleEvent方法。handleEvent方法在Choreographer的父类DisplayEventDispatcher中实现。

    在DisplayEventDispatcher的handleEvent方法中,会调用dispatchVsync方法,该方法在子类Choreographer中实现。
21
    在Choreographer的dispatchVsync方法中,主要做了两件事:

1)收集满足时间要求的FrameCallback。

2)调用FrameCallback中的回调方法。
22
    由于RenderThread在请求VSync信号时传入了静态方法extendedFrameCallback。因此当VSync信号到来时会调用RenderThread的静态方法extendedFrameCallback。

    在RenderThread的静态方法extendedFrameCallback中,主要做了两件事:

1)获取RenderThread。

2)调用RenderThread的frameCallback方法。
23
    在RenderThread的frameCallback方法中,主要做了两件事:

1)计算动画帧任务执行的目标时间点。

2)对dispatchFrameCallbacks方法进行封装,插入到WorkQueue中,等待到达目标时间点时threadLoop方法的循环任务处理。
24
    当RenderThread唤醒后,会执行任务队列中的任务,会调用dispatchFrameCallbacks方法。在RenderThread的dispatchFrameCallbacks方法中,主要做了两件事:

1)请求VSync信号。

2)执行动画帧任务。
25

四.Surface的绑定

    在ViewRootImpl的performTraversals方法中,会通过relayoutWindow方法创建Surface。当Surface创建好后,会调用ThreadedRenderer的initialize方法进行绑定。
26
    在ThreadedRenderer的initialize方法中,会调用setSurface方法。在ThreadedRenderer的setSurface方法中,会调用父类HardwareRenderer的setSurface方法。
27
    在HardwareRenderer的setSurface方法中,会调用nSetSurface方法。
28    HardwareRenderer的nSetSurface方法对应Native实现为android_graphics_HardwareRenderer的android_view_ThreadedRenderer_setSurface函数。

    在android_view_ThreadedRenderer_setSurface函数中,主要做了三件事:

1)获取RenderProxy。

2)将Java层Surface指针封装成ANativeWindow。

3)为RenderProxy设置Surface。
29
    在RenderProxy的setSurface方法中,会对CanvasContext的setSurface方法封装,添加到RenderThread的WorkQueue中等待执行。
30
    当RenderThread执行任务时,会调用CanvasContext的setSurface方法。在CanvasContext的setSurface方法中,主要做了三件事:

1)将ANativeWindow封装成ReliableSurface,ReliableSurface用于Hook拦截ANativeWindow的方法调用。

2)初始化ReliableSurface。

3)初始化渲染管线。
31
    在CanvasContext的setupPipelineSurface方法中,主要做了两件事:

1)获取ANativeWindow。

2)为渲染管线设置Surface。
32

五.总结

1.硬件渲染开启流程

    硬件渲染的开启发生在ViewRootImpl中。开启硬件渲染会进行两步操作:第一步是ThreadedRenderer的创建,第二步是ThreadedRenderer与Surface的绑定。

2.ThreadedRenderer的创建

    ThreadedRenderer的创建会触发Native层RootRenderNode和RenderProxy的创建。RootRenderNode是窗口渲染根节点。RenderProxy负责从UI线程向Render线程发送渲染指令。

2.1 RenderProxy的创建

    RenderProxy的创建会触发RenderThread、CanvasContext、DrawFrameTask的创建。RenderThread负责监听与请求VSync信号,在VSync信号到来时执行任务并请求下一次VSync信号。CanvasContext负责渲染节点的渲染与渲染管线的管理。DrawFrameTask负责硬件渲染中每一帧渲染任务的管理,包括布局的测量构建、多层级的管理等。

3.ThreadedRenderer与Surface的绑定

    ThreadedRenderer与Surface的绑定本质上是将Surface与CanvasContext中渲染管线的绑定。Java层Surface在进入Native层后会被封装成ANativeWindow。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值