Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx

上传人:b****4 文档编号:14021630 上传时间:2022-10-17 格式:DOCX 页数:76 大小:372.46KB
下载 相关 举报
Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx_第1页
第1页 / 共76页
Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx_第2页
第2页 / 共76页
Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx_第3页
第3页 / 共76页
Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx_第4页
第4页 / 共76页
Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx_第5页
第5页 / 共76页
点击查看更多>>
下载资源
资源描述

Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx

《Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx》由会员分享,可在线阅读,更多相关《Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx(76页珍藏版)》请在冰豆网上搜索。

Chromium硬件加速渲染的OpenGL上下文调度过程分析资料Word下载.docx

每一个OpenGL上下文都关联有一个绘图表面。

对于WebGL端和Render端的OpenGL上下文来说,它关联的绘图表面是一个离屏表面。

这个离屏表面一般就是用一个Pbuffer描述。

在Android平台上,Browser端的OpenGL上下文关联的绘图表面是一个SurfaceView。

当一个OpenGL上下文被调度时,它以及它关联的绘图表面就会通过调用EGL函数eglMakeCurrent设置为GPU线程当前使用的OpenGL上下文和绘图表面。

从前面一文又可以知道,Chromium为WebGL端、Render端和Browser端创建的OpenGL上下文可能是虚拟的,如图2所示:

在Chromium中,每一个虚拟OpenGL上下文都使用一个GLContextVirtual对象描述。

每一个虚拟OpenGL上下文都对应有一个真实OpenGL上下文,即一个GLContextEGL对象,并且所有的虚拟OpenGL上下文对应的真实OpenGL上下文都是相同的。

虚拟OpenGL上下文也像真实OpenGL上下文一样,关联有绘图表面。

对于WebGL端和Render端的虚拟OpenGL上下文来说,它关联的绘图表面也是一个使用Pbuffer描述的离屏表面。

在Android平台上,Browser端的OpenGL上下文关联的绘图表面同样也是一个SurfaceView。

当一个虚拟OpenGL上下文被调度时,它对应的真实OpenGL上下文以及它关联的绘图表面就会通过调用EGL函数eglMakeCurrent设置为GPU线程当前使用的OpenGL上下文和绘图表面。

由于所有的虚拟OpenGL上下文对应的真实OpenGL上下文都是相同的,因此当一个虚拟OpenGL上下文被调度时,只需要通过调用EGL函数eglMakeCurrent将其关联的绘图表面设置为GPU线程当前使用的绘图表面即可。

前面提到,OpenGL上下文有优先级高低之分,具体表现为Browser端的OpenGL上下文优先级比WebGL端和Render端的高。

这是因为前者负责合成后者的UI显示在屏幕中,因此就要保证它的运行时间。

在Browser端的OpenGL上下文需要调度运行而GPU线程又被其它OpenGL上下文占有时,Browser端的OpenGL上下文就可以抢占GPU线程。

为达到这一目的,Chromium给Browser端与GPU进程建立的GPU通道设置IDLE、WAITING、CHECKING、WOULD_PREEMPT_DESCHEDULED和PREEMPTING五个状态。

这五个状态的变迁关系如图3所示:

当Browser端的GPU通道处于PREEMPTING状态时,Browser端的OpenGL上下文就可以要求其它OpenGL上下文停止执行手头上的任务,以便将GPU线程交出来运行Browser端的OpenGL上下文。

Browser端的GPU通道开始时处于IDLE状态。

当有未处理IPC消息时,就从IDLE状态进入WAITING状态。

进入WAITING状态kPreemptWaitTimeMs毫秒之后,就自动进入CHECKING状态。

kPreemptWaitTimeMs毫秒等于2个kVsyncIntervalMs毫秒,kVsyncIntervalMs定义为17。

假设屏幕的刷新速度是60fps,那么kVsyncIntervalMs毫秒刚好就是一个Vsync时间,即一次屏幕刷新时间间隔。

处于CHECKING状态期间时,Browser端的GPU通道会不断检查最早接收到的未处理IPC消息流逝的时间是否小于2次屏幕刷新时间间隔。

如果小于,那么就继续停留在CHECKING状态。

否则的话,就进入WOULD_PREEMPT_DESCHEDULED状态或者PREEMPTING状态。

图1所示的stub指的是一个GpuCommandBufferStub对象。

从前面Chromium硬件加速渲染的OpenGL上下文创建过程分析一文可以知道,在GPU进程中,一个GpuCommandBufferStub对象描述的就是一个OpenGL上下文。

因此,图1所示的stub指的是一个Browser端OpenGL上下文。

处于CHECKING状态期间时,如果最早接收到的未处理IPC消息流逝的时间大于等于2次屏幕刷新时间间隔,并且没有任何的Browser端OpenGL上下文自行放弃调度,那么Browser端的GPU通道就会进入PREEMPTING状态,表示它要抢占GPU线程,也表示要求当前正在调度的OpenGL上下文放弃占有GPU线程。

另一方面,如果这时候至少有一个Browser端OpenGL上下文自行放弃调度,那么Browser端的GPU通道就会进入WOULD_PREEMPT_DESCHEDULED状态,表示它现在不急于抢占GPU线程,因为这时候有OpenGL上下文自行放弃了调度,从而使得最早接收到的未处理消息所属的OpenGL上下文得到调度处理。

处于WOULD_PREEMPT_DESCHEDULED状态时,Browser端的GPU通道会继续检查是否有Browser端OpenGL上下文自行放弃调度。

如果没有,那么就进入PREEMPTING状态,表示要抢占GPU线程。

如果有,并且这时候Browser端的GPU通道接收到的IPC消息均已被处理,或者最早接收到的未处理IPC消息的流逝时间小于kStopPreemptThresholdMs毫秒,那么就进入IDLE状态。

否则的话,就继续维持WOULD_PREEMPT_DESCHEDULED状态。

kStopPreemptThresholdMs也定义为17,意思是Browser端的GPU通道处于WOULD_PREEMPT_DESCHEDULED状态时,允许最早接收到的未处理IPC消息延迟一次屏幕刷新时间间隔再进行处理。

Browser端的GPU通道处于PREEMPTING状态的最长时间为kMaxPreemptTimeMs毫秒。

kMaxPreemptTimeMs也定义为17,意思是Browser端的GPU通道抢占GPU线程的时间不能超过一个屏幕刷新时间间隔。

如果超过了一个屏幕刷新时间间隔,那么就会进入IDLE状态。

在处于PREEMPTING状态期间,如果Browser端的GPU通道接收到的IPC消息均已被处理,或者最早接收到的未处理IPC消息的流逝时间小于kStopPreemptThresholdMs毫秒,那么Browser端的GPU通道也会进入IDLE状态。

此外,在处于PREEMPTING状态期间,如果至少有一个Browser端OpenGL上下文自行放弃调度,那么Browser端的GPU通道就会进入WOULD_PREEMPT_DESCHEDULED状态。

注意,在图3所示的状态变迁图中,只有处于PREEMPTING状态时,Browser端的GPU通道才会强行抢占GPU线程。

这是为了保证Browser端的OpenGL上下文,至少应该需要在两个屏幕刷新时间间隔之内,得到一次调度,从而保证网页UI得到刷新和及时显示。

WebGL端和Render端的OpenGL上下文就没有这种待遇,毕竟它们的优先级没有Browser端的OpenGL上下文高。

Browser端GPU通道是以什么方式强行抢占GPU线程的呢?

我们通过图4说明,如下所示:

Browser端GPU通道有一个PreemptionFlag。

当它处于PREEMPTING状态时,就会将PreemptionFlag设置为True。

WebGL端和Render端GPU通道可以访问Browser端GPU通道的PreemptionFlag。

属于WebGL端和Render端GPU通道的OpenGL上下文在调度期间,会不断地检查Browser端GPU通道的PreemptionFlag是否被设置为True。

如果被设置为True,那么它就会中止执行,提前释放GPU线程。

WebGL端和Render端GPU通道和Browser端GPU通道是父子关系。

其中,WebGL端和Render端GPU通道是儿子,Browser端GPU通道是父亲。

Chromium规定,儿子GPU通道可以访问父亲GPU通道的PreemptionFlag。

有了前面这些背景知识之后,接下来我们就结合源码分析OpenGL上下文的调度过程。

从前面一文可以知道,GPU进程通过调用GpuChannel类的成员函数Init创建GPU通道,如下所示:

[cpp]viewplaincopy

voidGpuChannel:

:

Init(base:

MessageLoopProxy*io_message_loop,

base:

WaitableEvent*shutdown_event){

......

channel_=IPC:

SyncChannel:

Create(channel_id_,

IPC:

Channel:

MODE_SERVER,

this,

io_message_loop,

false,

shutdown_event);

filter_=

newGpuChannelMessageFilter(weak_factory_.GetWeakPtr(),

gpu_channel_manager_->

sync_point_manager(),

MessageLoopProxy:

current());

channel_->

AddFilter(filter_.get());

}

这个函数定义在文件external/chromium_org/content/common/gpu/gpu_channel.cc中。

结合前面一文可以知道,WebGL端、Render端和Browser端发送过来的GPU消息由GpuChannel类的成员函数OnMessageReceived负责接收。

在接收之前,这些GPU消息首先会被GpuChannel类的成员变量filter_指向的一个GpuChannelMessageFilter对象的成员函数OnMessageReceived过滤。

注意,GpuChannel类的成员函数Init是在GPU线程中执行的,这意味着GpuChannel类的成员函数OnMessageReceived也将会在GPU线程中执行,但是它的成员变量filter_指向的GpuChannelMessageFilter对象的成员函数OnMessageReceived不是在GPU线程执行的,而是在负责接收IPC消息的IO线程中执行的。

接下来我们先分析GpuChannel类的成员函数OnMessageReceived的实现,后面分析Browser端GPU通道抢占GPU线程的过程时,再分析GpuChannelMessageFilter类的成员函数OnMessageRe

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 卡通动漫

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1