版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Chromium的GPU进程启动过程分析
Chromium除了有Browser进程和Render进程,还有GPU进程。GPU进程负责Chromium的GPU操作,例如Render
进程通过GPU进程离屏渲染网页.Browser进程也是通过GPU进程将离屏渲染好的网页显示在屏幕上。Chromium
之所以将GPU操作运行在独立进程中,是考虑到稳定性问题。终归GPU操作是硬件相关操作,硬件的差异性会引
发肯定的不稳性。本文分析GPU进程的启动过程.
GPU进程由Browser进程负责启动,它的启动过程及Render进程的启动过程是类似的,因此在阅读本文之前,最
好先阅读一文。不过,GPU进程启动之后,Browser进程会及它建立两个IPC通道。一个IPC通道用来传输一般的
IPC消息,另一个IPC通道特地用来执行GPU操作,称为GPU通道,类似地,Render进程须要执行GPU操作时,
也会通过Browser进程及GPU进程建立一个特地用来执行GPU操作的IPC通道。Render进程之所以要通过Browser
进程间接地及GPU进程建立GPU通道,是因为GPU进程是由Browser进程启动的,Render进程充它一窍不通。
以上描述的Browser进程、Render进程和GPU进程的关系可以通过图1概括,如下所示:
10Thread
GpuChano^
lOnifftadThre>d
Chanel
GouChanAei
图1Browse总程、Rende谜程和GPU进程的关系
在图1中,Browser进程及Render进程的IPC通道的建立过程可以参考前面一文,本文只分析以下三部分内容:
1.Browser进程及GPU进程的IPC通道的建立过程.
2。Browser进程及GPU进程的GPU通道的建立过程。
3。Render进程及GPU进程的GPU通道的建立过程。
Browser进程通过一个GpuProcessHost对象描述由它启动的GPU进程。GPU进程启动起来之后,会创建
一个GpuProcess对象用来及Browser进程进行IPC。接下来,Browser进程中的GpuProcessHost对象会通过已经建
立起来的IPC通道恳求GPU进程中创建一个GPU通道,以便以后可以执行GPU操作.
Render进程须要通过GPU渲染网页的时候,会通过之前及Browser进程建立的IPC通道恳求Browser进程
为它创建一个GPU通道,并且将该GPU通道封装在一个WebGraphicsConlexGDCommandBufferlmpl对象,以后就
可以通过该WebGraphicsContext3DCommandBufferInipI对象向GPU进程恳求执行GPU操作了。
GPU进程在启动的过程中,也会像Browser进程和Render法程一样,启动一个IO线程,特地用来执行IPC。
以后每当GPU进程通过上述IPC通道接收到一个创建GPU通道的出求的时候,都会在内部创建一个OpenGL上下
文.这个OpenGL上下文通过一个GLContext对象描述。这样在GPU进程中,就会存在若干个OpenGL上下文。这
些OpenGL上下文都运行在同一个线程中,这个线程称为GPUChildThread.这样就会涉及到一个OpenGL上下文
调度问题,即每当GPU进程接收到一个GPU操作恳求时,都要先切换到恳求的GPU操作所在的OpenGL上下文,
然后才能执行恳求的GPU操作。关于GPU进程的OpenGL上下文调度问题,我们在下一系列的文章中再具体分
析。
接下来,我们就先分析Browser进程启动GPU进程的过程.这个过程主要是涉及到Browser进程和GPU进
程的IPC通道的建立过程。
在前面一文中,我们提到,Browser进程,也就是Chromium应用程序的主进程,在启动的时候,会调用
BrowserMainLoop类的成员函数CreateStartupTasks.BrowserMainLoop类的成员函数CreateStartupTasks会恳求启动
一个GPU进程,相关的代码如下所示:
[cpp]viewplaincopy
voidBrowserMainLoop::CreateStartupTasks(){
•o・。o・
//Firstlimethrough,wereallywanttocreateallthetasks
if(!startup_lask_runner_oget()){
startup_task_runner_=make_scoped_ptr(newStartupTaskRunner(
base::Bind(&BrowserStartupComplete),
base::MessageLoop::current()—〉message_loop_proxy()));
O0o.•o
StartupTaskbrowser_ihread_started=base::Bind(
&BrowserMainLoop::BrowserThreadsStarted,base::Unretained(this));
startup_task_runner_->AddTask(browser_thread_started);
if(BrowserMayStartAsynchronously()){
startup_task_runner_—〉StartRunningTasksAsync();
)
if(!BrowserMayStartAsynchronously()){
。0♦・・。
startup_task_runner_->RunAHTasksNow();
)
)
这个函数定义在文件external/chromium_org/content/browsei7browser_main」oop.cc中。
BrowserMainLoop类的成员函数CreateStartupTasks首先是会创建一个StartupTaskRunner对象,并且保存在
成员变量startup_task_runner_4,o这个SlartupTaskRunner对象封装了当前线程的,个消息循环,因此通过它可以
向当前线程的消意队司发送福息。当前线程即为Browser进程的主线程,因此有了这个SlartupTaskRunner对象之
后,接下来可以向其主线程的消息队列发送消息。
BrowserMainLoop类的成员函数CreateStartupTasks接下来创建了一个StartupTask,这个StartupTask绑定
的函数为BrowserMainLoop类的成员函数BrowscrThrcadsStaricd,用来执行一个Browser线程启动完毕任务,并11会
保存在前面创建的一个StariupTaskRunner对象的内部等待执行。
最终,取决FBrowser进程运用同步还是异步方式启动,BrowserMainLoop类的成员函数CreateStartupTasks
运用不同的方式来执行保存在成员变量siarlup」ask_runneiJ|^J的一个StartupTaskRunner对象中的StartupTask:
1o假如是运用同步方式启动,那么就调用上述SiarlupTaskRunner对象的成员函数RunAHTasksNow马上执
行保存在它里面的各个StartupTask对象所描述的任务。
2.假如是运用异步方式启动,那么就调用上述SiarlupTaskRunner对象的成员函数SlarlRunningTasksAsync
向主线程的消息队列发送一个消息,当该消息被处理时,再执行保存在上述StartupTaskRunner对象里面的各个
StartupTask对象所描述的任务。
无论是同步方式,还是异步方式,最终都会在主线程中调用BrowserMainLoop类的成员函数
BrowserThreadsStarted,及GPU进程启动相关的代码如下所示:
[cpp]viewplaincopy
intBrowserMainLoop::BrowserThreadsStarted(){
boolini(ialize_gpu_da(a_manager=true;
#ifdefined(OS_ANDROID)
//OnAndroid.GLSurfacc::InitializcOncOff()mustbecalledbeforeinitalizing
//theGpuDataManagcrlmplasitusestheGLbindingSoerbugocornG26295
if(!gfx::GLSurface::InitializeOneOff()){
・・oo•o
initialize_gpu_data_manager=false;
)
#endif
if(initialize_gpu_data_manager)
GpuDataManagerlmpI::Getlnstance()—>Initialize():
boolalways_uses_gpu=true:
beolestablished_gpu_channel=false;
#ifdefined(USE_AURA)||defined(OS-MACOSX)
if(ShouldInitializeBrowsei<jpuChanneIAndTransportSurface()){
establishcd_gpu_channcl=true:
if(JGpuDataManagcrhnpl::GctInstance()->CanUscGpuBrowscrCoinpositor()){
established_gpu_channel=always_uses_gpu=false:
)
BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
o••o。•
}
#clifdefined(OS_ANDROID)
establishcd_gpu_channcl=true;
BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
#endif
这个函数定义在文件external/chroinium_org/content/browser/browser_main_loop.cc中。
在Android平台上,BrowscrMainLoop类的成员函数BrowscrThreadsStartcd首先调用gfx::GLSurfacc类的
静态成员函数InitializeOneOff在当进程中加载合适的OpenGL阵,以及创建一个EGLDisplayu这样做有两个缘
由,一是局面调用GpuDataManagerlmpI类的成员函数Initialize时,在Android平台上须要通过加载的OpenGL库
来获得GPU信息,二是Android平台的Chromium事实上并没有独立的GPU进程,而是在Browser进程中创建一
个GPU线程,不过这个GPU线程起到的作用及GPU进程是一样的。上述其次个缘由要求Browser进程要做一些
GPU相关的初始化工作,即加载合适的OpenGL库,以及创建•个EGLDisplay,以后创建OpenGL上下文时须要
运用到这个EGLDisplay.对于独立GPU进程的状况,上述的GPU初始化也是须要做的。后面我们就会看到,GPU
进程在启动的时候,会调用gfx::GLSurfacc类的静态成员函数InitializeOneOffo
只有在gfx::GLSurfacc类的静态成员函数InitializeOneOff的返回值为true,即在当进程中胜利加载了合适
的OpenGL库之后,BrowscrMainLo叩类的成员函数Initialize才会被调用,负责检查当前设备运用的GPU及其相
关的驱动是否在黑名单中。假如在黑名单中,那么Chromium就不会采纳GPU对网页进行硬件加速渲染.这是由于
不是全部的GPU都能够很好地支持Chromium进行硬件加速渲染,因此就须要设匿一个黑名单,避开在渲染网页
的过程中出现错误。一旦不能运用GPU对网页进行硬件加速渲染,那么Chromium就会退而求其次,运用CPU进
行消染。
假如Chromium在编译时定义了宏USE_AURA,那么就表示要运用GPU对网页进行硬件加速渲染,这时候就
可能须要启动GPU进程。AURA是Chromium35引入的一个窗口管理框架,通过GPU来实现界面上的像按钮、
滚动条和对话框等界面控件。但是由于GPU黑名单的存在,因此就不肯定能够如愿地运用GPU对网页进行硬件加
速渲染。这时候就须要进一步调用函数ShouldlnitializcBrowscrGpuChannclAndTransportSurface以及
GpuDataManagerlmpI类的成员函数CanUseGpuBrowserCompositor进行推断。假如最终确定不能够运用GPU对网
页进行硬件加速渲电,那么接下来在调用BrowserGpuChannelHoslFack)r),类的静态成员函数Initialize的时候,传递
进去的参数就会等于falseo对于MacOSX平台,也会进行相同的处理。
假如Chromium在编译时没有定义宏USE_AURA,但是当前平台是Android,那么BrowserMainLoop类的
成员函数BrowserThreadsStarted就干脆将本地变量established_gpu_channel设置为true,并且以其为参数,调用
Bro\vsei<ipuChannelHostFactoi3,类的静态成员函数Initialize启动一个GPU进程。这表明在Android平台上,要求
GPU能够支持Chromium对网页进行硬件加速渲染.
为了更好地理解上面分析的内容,接下来我们在分析GPU进程的启动过程,也就是
BrowserGpuChannelHostFactoi3,类的静态成员函数Initialize之前,先分析以下几个函数:
Iogfx::GLSurfacc::InitializcOncOff
2.GpuDataManagcrlmpl::Initialize
3.ShouldlnitializeBrowserGpuChannelAndTransportSurface
4.GpuDataManagerlmpI::CanUseGpuBrowserCompositor
gfx::GLSurface类的静态成员函数InitializeOneOff负责在当前进程中加载合适的OpenGL库,它的实现如
下所示:
[cpp]viewplaincopy
boolGLSurface::InitializeOneOff(){
std::vector(GLImplemenlation>allowed_impls;
GetAllowedGLImplementations(&allowed_impls);
oo.0oo
CommandLine*cmd=CommandLine::ForCurrentProcess();
//Thedefaultimplementationisalwaysthefirstoneinlist.
GLImplementationimpl=allowed_impls[0]:
boolfallback_io_osmesa=false;
if(cmd-)HasSwitch(switches::kOverrideUseGLWithOSMesaForTests)){
impl=kGLImplcmcntationOSMcsaGL;
}elseif(cmd—〉HasSwitch(switches::kUseGL)){
std::stringrequested_implemen(ation_name=
cmd—>GctSwitchValucASCII(switches::kUscGL):
if(reques(ed_implementation_name=="any"){
fallback_to_osmesa=true;
}elseif(requested_implementation_name=="swiftshader"){
impl=kGLImplementationEGLGLES2;
}else(
impl=GeiNaniedGLImplememauon(requested_implementation_name);
if(std::find(allowed_implstbegin(),
allowed_implsoend(),
impl)==allowed_impls.end()){
returnfalse;
)
)
)
re:umInitializeOneOfninplementalion(
impl,fallback_to_osmesa,gpu_service_logging,disable_gl_drawing);
)
这个函数定义在文件external/chromium_org/ui/gl/gl_surface.cc中.
gfx::GLSurface类的静态成员函数InitializeOneOff首先是调用另外一个函数
GetAllowedGLImplementations获得当前平台所支持的OpenGL实现版本列表。对于Android平台花的实现如下所
示:
[cpp]viewplaincopy
voidGetAllowedGLImplementations(std::vector<GLImplementation)*impls){
impls—>push_back(kGLImplementationEGLGLES2);
impls->push_back(kGLImplcmcntationOSMesaGL);
)
这个函数定义在文件extcrnal/chro【nium_org/ui/g】/gl_implementa【ion_android.cc中。
从这里可以看到,在Android平台上,Chromium支持两个版本的OpenGL实现,其中一个是
kGLImplementationEGLGLES2,另一个是kGLImplementationOSMesaGL»kGLImplementationEGLGLES2描述的
OpenGL即为Android系统本身供应的OpenGL实现,这个就是由底层的GPU实现的OpenGL库。
kGLImplementationOSMesaGL描述的OpenGL是由Mesa实现的OpenGL库.Mesa是一个开源的OpenGL实现框架.
它可以以软件方式模拟GPU硬件加速渲染,也可以通过底层真实的GPU来实现硬件加速渲染。
问到gfx::GLSurface类的静态成员函数InitializeOneOff中,它获得当前平台所支持的OpenGL实现版本
列表之后,取出列表中的第•个版本作为默认版本。从前面的分析就可以知道,对于Android平台,这个默认的
OpenGL实现版本就是kGLImplcmcntationEGLGLES2描述的版本。
接下来,Mx::GLSurface类的静态成员函数InitializeOneOff再依据吩咐行参数选择最终运用的OpenGL
实现版本:
1.假如设置了switches::kOverrideUseGLWithOSMesaForTests选项,那么就表示要运用
kGI.ImplementationOSMesaGI.描述的QpcnGL版本.便利用来测试,
2.假如设置了switches::kUseGL选项,那么就依据这个选项的值选择指定的OpenGL实现。不过有两种
特别状况.一是当该选项值等于“any"时,默认运用之前选择的OpenGL实现版本,但是假如不能胜利加载该版本
的库,那么就改为运用kGLImplementaiionOSMesaGL描述的OpenGL版本。二是当该选项的值等于"swiftshader"
时.,运用kGLImplemenialionEGLGLES2描述的OpenGL版本。SwifiShader是一件纯软件实现的3D渲染引擎工具,
由TransGaming公司实现,宣称支持全部的Pixel和VertexShaderDX9特效,并且可以获得比微软D3D的REF设备
(referencerasterizer)快50倍的速度。在Android平台上,没有供应SwiftShader,因此用
kGLImplementationEGLGLES2描述的OpenGL版本替代。
最终,gfx::GLSurface类的静态成员函数InitializeOneOff调用另外一个成员函数
InitializeOneOfflmplementation在当前进程中加载前面所选择的OpenGL实现版本,它的实现如下所示:
[epp]viewplaincopy
boolGLSurface::InitializeOneOfnmplementaiion(GLImplementationimpl,
boolfallback_to_osincsa,
boolgpu_service_logging,
booldisablc_g^_drawing){
bc-olinitialized=
InitiaiizcStaticGLBindings(impl)&&InitializcOncOfflntcrnal();
if(!initialized&&fallback_to_Dsmesa){
ClearGLBindings();
initialized=InitializeStaticGLBindings(kGLImplementationOSMesaGL)&&
InitializeOneOffliitemal();
)
if(!initialized)
ClearGLBindings();
returninitialized:
)
这个函数定义在文件external/chromium_org/ui/gl/gl_surface.cc中。
gfx::GLSurface类的静态成员函数InitializeOneOfflmplementation首先调用函数InitializeStaticGLBindings
加载由参数inipl指定的OpenGL实现版本相关的库.假如能胜利加载,再调用函数InitializeOneOfflnlemal在当前龙
程中创建一个EGLDisplayo假如也能胜利创建这个EGLDisplay,那么就说明参数指定的OpenGL实现版本是能够
正确运用的。
假如不能胜利加载参数impl指定的OpenGL实现版本相关的库,或者能够胜利加载,但是不能胜利创建一
个EGLDisplay,并且参数fallback_to_osmesa的值为true,那么就如前所述,改为运用kGLImplementaiionOSMesaGL
描述的OpenGL实现版本,也就是由Mesa实现的OpenGL库。
接下来,我们先分析函数InilializcStaticGLBindings的实现,接着再分析函数InitializcOncOfflntcrnal的实
现。
函数InilializcStaticGLBindings的实现如下所示:
[eppjviewplaincopy
boolInitializeStaticGLBindings(GLIniplementationimplementation){
switch(implementation){
casekGLImplementationEGLGLES2:{
base::NativcLibraryglcs_library=
LoadLibraryAndPrintError("libGLESv2oso”):
base::NativeLibraryegllibrary=LoadLibra^AndPrintErn)r(,,libEGL.soM);
0。・。0・
GLGctProcAddrcssProcgct_proc_addrcss=
reinterpret_cast<GLGetProcAddressProc)(
base::GetFunctionPointerFromNativeLihrary(
cgUibrary,"eglGclProcAddress"));
o•ooo•
SetGLGetProc/XddressProc(get_proc_address);
AddGLNaliveLibrary(egl」ibrary):
AddGLNativeLibrary(gles_library);
SetGLImplementation(kGLImplementationEGLGLES2);
InitializcStaticGLBindingsGL();
1nitializeStaticGLBindingsEGL();
••oooo
break:
)
)
returntrue;
)
这个函数定义在文件external/chn)mium_org/ui/gl/gl_implementation_android.cc中。
从这里就可以看到,及kGLImplementationEGLGLES2描述的OpenGL实现版本相关的库有两个,分别为
libGLESv2.so和libEGL.so,前者描述的是OpenGL实现,后者描述的是EGL实现。调用函数
LoadLibraryAndPrintError加载了这两个库之后,最终分别调用了函数InitializeStaticGLBindingsGL和
InitializeStaticGLBindingsEGL创建了•个RealGLApi接口和•个RealEGLApi接口,这样以后就可以通过这两个接
口调用由前面加载的libGLESv2.so和libEGL。so所导出的gl*和eg]*函数。
这一步执行完成之后,回到前面分析的gfx::GLSurfacc类H勺静态成员函数InitializcOncOfflmplcmcntation
中,它接下来调用函数InitializcOncOfflntcrnal创建一个EGLDisplay,以验证前面加载的OpenGL相关的库的正确
性。
函数InitializcOncOftlntcrnal的实现如下所示:
[epp]viewplaincopy
boolGLSiirfacc::InitializcOncOfnntcrnal(){
switch(GetGLImplementation()){
casekGLImplementationEGLGLES2:
if(!GLSurfaceEGL::InitializeOneOff()){
LOG(ERROR)(〈”GLSurftceEGL::lnitializeOneO汗faled”;
retumfalse;
)
default:
break;
)
returntrue;
)
这个函数定义在文件extemal/chr()mium_org/ui/gl/gl_surface_androidocc中。
从这里可以看到,当运用kGLImplementationEGLGLES2描述的OpenGL实现版本时,函数
InitializeOneOfflnternal调用GLSurfaceEGL类的静态成员函数InitializeOneOff创建一个EGLDisplay.
GLSurfaceEGL类的静态成员函数InitializeOneOff的实现如下所示:
|cpp|viewplaincopy
boolGLSurfaceEGL::InitializeOneOffO{
staticboolinitialized=false;
if(initialized)
returntrue:
g_native_display=GctPlatfbnnDcfaultEGLNativcDisplay():
g_display=eglGetDisplay(g_native_display);
if(!g_display){
returnfalse;
)
if(!egllnitialize(g_display,NULL,NULL)){
ooo••o
returnfalse;
)
staticconstEGLintkConfigAttribs[]={
EGL_BUFFER_SIZE,32,
EGL_ALPHA_SIZE,8,
EGL_BLUE_SIZE,8,
EGL_GREEN_SIZE,8.
EGL_RED_SIZE,8,
EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE,EGL_WINDOW_BITIEGL_PBUFFER_BIT,
EGL_NONE
):
constEGLint*config_attribs=kConfigAttribs;
EGLintnum_configs;
if(!eglChooseConfig(g_display,
config_attribs»
NULL,
0,
&num_configs)){
•••o。o
returnfalse;
)
initialized=true;
returntrue;
)
这个函数定义在文件external/chromium_org/ui/gl/gl_surface_egl。cc中.
从这里可以看出,GLSurfaceEGL类的静态成员函数InitializeOneOff通过调用egl函数eglGetDisplay
egllnitialize和eglChooseConfig创建•个EGLDisplay,并且保存在全局变量g_display中,以后就可以通过这个
EGLDisplay来创建OpenGL上下文.事实上,eglGclDisplay、egllnitialize和eglChooseConfig是定义在
out/target/product/generic/obj/GYP/sha-ed_intermediates/ui/gl/gl_bindings_autogen_egLh文件中的三个宏,它们分别
定义为前而加载的libEGLoso所导出的三个函数eglGetDisplay、egllnitialize和eglChooseConfig。
事实上,文件out/largel/product/generic/obj/GYP/shared_inlermediates/ui/gl/gl_bindings_aulogen_egl。h定义/
全部的egl*宏,并且这些宏都定义为前面加载的libEGL.so所导出的对仓的egl*函数.尾似地,文件
out/target/pn>duct/generic/obj/GYP/shcred_intermediates/ui/gl/gl_bindings_autogen_gloh也定义了全部的gl大宏,并
且这些宏都定义为前面加载的libGLESv2.so所导出的对应的gl火函数。
最终♦out/target/producl/generic/obj/GYP/shared_intermediates/ui/gl/gl_bindings_aut()gen_egl.h和
out/tiirget/pr(>duct/generic/obj/GYP/shtred_intermediates/ui/gl/gl_bindings_autogen_gloh也定义了全部的gl*宏,并且
这些宏都定义为前面加载的libGLESv2.so所导出的对应的gl*函数.这两个文件又被文件
external/chromium_org/ui/gl/gl_bindings.li所included.因此只要include\extemal/chromium_org/ui/gl/gl_hindingsnh
文件,就可以干脆调用全部的由前面加载的libGLESv2.so和libEGLoso导出的gl*和egl*函数。
这一步执行完成之后,问到前面分析的BrowserMainLoop类的成员函数BrowserThreadsStarted中,假设
gfx::GLSurface类的静态成员函数InitializeOneOff的返向值为true,即它胜利加载了OpenGL相关的库,那么接下
来就会调用GpuDataManagcrlinpl类的成员函数Initialize检查设备配置的GPU是否在黑名单列表中,
GpuDataManagerlmpI类的成员函数Initialize的实现如下所示:
[cpp|viewplaincopy
voidGpuDataManagerlmpI::Initialize(){
base::AutoLockauto_lock(lock_);
private.—〉Initialize();
)
这个函数定义在文件external/clironiiuni_oig/content/browser/gpu/gpu_data_manager_implocc中。
GpuDataManagerlmpI类的成员变量private.指向的是•个GpuDataManagerlmplPrivale对象,这里调用它的
成员函数Initialize检查设备配置的GPU是否在黑Z单列表中。
GpuDataManagerlmpIPrivate类的成员函数Initialize的实现如下所示:
[epp]viewplaincopy
voidGpuDataManagerlmplPrivate::Initialize(){
gpu::GPUInfogpu_infb;
if(commandJine->GctSwitchValucASCII(
switches::kUseGL)==gfx::kGLImplernentationOSMesaName){
//IfusingtheOSMesaGLimplementation,usefakevendoranddeviceidsto
//makesureitnevergetsblacklisted。Thisisbetterthansimply
//cancellingGPUIntbgatheringasi(allowsustoproceedwithloadingthe
//blacklistbelowwhichmayhavenon-devicespecificentrieswewantto
//applyanyways(e«go,OSversionblack!isting)0
gpu_info.gpiiovendor_id=Oxffff;
gpu_infb.gpu.dcvicc_id=Oxffff;
//Alsodeclarethedriver_vend()rtobeosmesatobeabletospecify
//exceptionsbasedondriver_vendor==osmesaforsomeblacklistrules.
gpu_info.driver_vendor=gfx::kGLImplernentationOSMesaName;
}else(
oo•o・・
gpu::CollectBasicGraphicsInfo(&gpu_infb);
)
std::stringgpu_blacklist_string;
std::stringgpu_drivcr_bug_list_strmg;
if(!commandjine—>HasSwitch(switches::klgnoreGpuBlacklist)&&
!command_line—〉HasSwitch^switches::kUseGpuInTests)){
gpu_blacklist_string=gpu::kSoftwarcRcndcringListJson;
)
if(!commandjine—)HasSwitch(switches::kDisableGpuDriverBugWorkarounds)){
gpu_driver_bug_list_stiing=gpu::kGpuDriverBugListJson:
)
Initializelmpl(gpu_blacklist_string,
gpu_drivcr_bug_list_string,
gpu_info);
)
这个函数定义在文件external/chroiniurn_org/content/browser/gpu/gpu_data_inanager_iinpl_private.cc中.
假如Chromium启动时,指定了switches::kUseGL选项,并且将该选项的值设置为
gfx::kGLImplementaiionOSMesaNamc,那么就意味着要运用Mesa版本的OpenGL库来渲染Chromium的UL由「这
里运用的Mesa版本的OpenGL库是纯软件实现的,因此它不会像GPU版本的OpenGL库一样存在一些不友好特
性.也就是说Mesa版本的OpenGL库是可用的,尽管它的性能会差一些。为了避开后面加载GPU黑名单列表时,
列表中的某些通用规则会禁用Mesa版本的OpenGL库的某些特性,GpuDataManagerlmpIPrivate类的成员函数
Initialize会手工构造一个GPUInfo对象,并且给该GPUInfo对象设置假的VendorID和DeviceID,以及Driver
Vendorn
假如Chromium启动时,没有指定switches::kUseGL选项,或者指定了switches::kUseGL选项,但是该选
项的值没有设置为gfx::kGLImplementationOSMesaName,那么上述GPUInfo对象就须要通过函数gpu::
CollectBasicGraphicsInfo来构造。函数gpu::CollectBasicGraphicsInfo通过OpenGL接口glGetString获得当前运用
的OpenGL库的VendorID和DeviceID,以及DriverVendor等值。
接下来,GpuDataManagerlmpIPrivate类的成员函数Initialize检查Chromium的吩咐行参数是否设置了
switches::klgnorcGpuBlacklist和swiichcs::kUseGpuInTcsis选项嘏如都没有设置,就说明Chromium是运行在
发布版本中,这时候须要启用GPU黑名单列表。这个GPU盘名单列表通过全局变量gpu::
kSoftwareRenderingLisUson描述的一个JSON格式的字符串描述,它定义在文件
external/chr(>mium_org/gpu/conflg/sofiware_rendering_lis(_jsoncc中.例如,在该GPU黑名单列表中,存在以下一
项:
[plain]viewplaincopy
(
I,
“description":"ATIRadeonXI900isnotcompatiblewithWebGLontheMac”,
"webkit_bugs":[47028],
"os":{
"type":"macosx"
),
,,,,
vendor_id;”0x1002”,
ndevice_idM:[,,0x7249"],
“features":[
"webgl",
"flash_3d",
"flash_stage3d"
]
}
它表示VendorID和DeviceID分别等于0x1002和0x7249的GPU在MacOSX上不能够用来支持Chromium
的webgRflash_3d和flash_stage3d特性。
再接下来,GpuDataManagerlmpIPrivate类的成员函数Initialize检查Chromium的吩咐行参数是否设置了
switches::kDisableGpuDriverBugWorkarounds选项“假如没有设置,也说明Chromium是运行在发布版本中,这
时候须要启用GPU驱动BUG列表。GPU驱动BUG列表描述了那些已知的GPU驱动的BUG,这些BUG也会导致
OpenGL的某些特性不能运用。这个GPU驱动BUG列表通过全局变量gpu::kGpuDriverBugLisUson描述的一个
JSON格式的字符串描述,它定义在文件external/chromium_org/gpu:config/gpu_driver_bug_lisjjson.ee中.例如,在
该GPU驱动BUG列表中,存在以下一项:
[plain]viewpkiincopy
{
“id“:8,
"descriplion“:"Afewbuilt-inglslfunctionsonMacbehaveincorrecUy”,
“cr_bugs”:[349137],
“os”:{
"type":"macosx",
“version":{
"op":
“value":"10.9”
)
),
”vendor_id“:"0x1002",
"features":[
,,needs_glsl_built_in_funciion_emulation"
1
)
它表示VenderID等于0x1002的GPU驱动的编号为349137的BUG会出现在版本号小于10.9的MacOSX
上,Chromium的needs_glsl_built_in_function_emulalion特性不行用
最终,GpuDataManagerlmpIPrivate类的成员函数Initialize将前面获得的GPUInfo对象,以及GPU黑名单列
表和GPU驱动BUG列表,传递给另外一个成员函数Initializelmpl进一步处理,如下所示:
[cpp]viewplaincopy
voidGpuDaiaManagerlmplPrivate::lnitializelmpl(
constsid::string&gpu_blacklist_json,
consts(d::string&gpu_driver_bug_iistjson,
constgpu::GPUInfo&gpu_info){
•o••oo
if(!gpu_blacklistJson(>empty()){
gpu_b)acklist_.reset(gpu::GpuBlacklist::Creale());
•oooo•
boolsuccess=gpu_blacklist_—>LoadList(
gpu_blacklistjson,gpu::GpuControlList::kCurrentOsOnly);
•ooo。・
)
if(!gpu_diiver_bug_list_json.empty()){
gpu_driver_bug_list_(>reset(gpu::GpuDriverBugList::Create());
。0。・・。
boolsuccess=gpu_driver_bug_list_->LoaclList(
gpu_drivcr_bug_listjson.gpu::GpuControlList::kCurrentOsOnly);
gpu_info_=gpu_infb;
UpdateGpuInfo(gpu_info);
o••o••
)
这个函数定义在文件external/chromium_org/conten(/browser/gpu/gpu_data_manager_impl_private.cc中.
GpuDaiaManagerlmplPrivate类的成员函数Initializelmpl首先是创建一个GpuBlackList对象,保存在成员变
量gpu_blacklist_l|4,并且调用该GpuBlackList对象的成员函数LoadList解析参薮gpu_
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中国联通IT支持工程师技术能力考试题库含答案
- 比亚迪汽车销售经理面试题目详解
- 网络教育中的教育产品经理面试题
- 狼疮性肾炎饮食安全与营养协同策略
- 人力资源专员面试题及答案宝典
- 人力资源岗位面试题及答案
- 2026届八省联考(T8联考)2026届高三年级12月检测训练英语试卷(含答案详解)+听力音频+听力材料
- 冷轧板(卷)建设项目可行性分析报告(总投资9000万元)
- 律师面试问题集法律专业篇
- 深度解析(2026)《GBT 18805-2002商品条码印刷适性试验》(2026年)深度解析
- 机械图样绘制与识读智慧树知到期末考试答案章节答案2024年沈阳职业技术学院
- DLT817-2014立式水轮发电机检修技术规程
- 高三下学期二模语文试卷汇编:写作专题
- 外科学手术器械的维护与保养
- 自愿放弃入伍承诺书
- 铝板拆除施工方案
- 植入式静脉给药装置(输液港)-中华护理学会团体标准2023
- 0031预防成人经口气管插管非计划性拔管护理专家共识
- THMSRX型实训指导书
- 原发性支气管肺癌教案
- GB/T 23280-2009开式压力机精度
评论
0/150
提交评论