接前一篇文章:Chromium源码由浅入深(一)
上一回解析了网页中的gpu相关信息在代码中的定位以及appendFeatureInfo_函数,本回沿着其上游即调用appendFeatureInfo_函数的调用栈网上追溯。
上回书中暂时没有管传给appendFeatureInfo_函数的实参,那么本回来看一下实参具体是什么值,是在哪里调用传递的。
在Chromium(v111)源码中搜索“appendFeatureInfo_”,可以看到共有两处调用,都是位于content/browser/resources/gpu/info_view.js中的browserBridge函数(该函数其实就在appendFeatureInfo_函数的上边)中,代码如下:
/**
* Updates the view based on its currently known data
*/
refresh(browserBridge) {
let clientInfo;
function createSourcePermalink(revisionIdentifier, filepath) {
if (revisionIdentifier.length !== 40) {
// If the revision id isn't a hash, just use the 0.0.0.0 version
// from the Chrome version string "Chrome/0.0.0.0".
revisionIdentifier = clientInfo.version.split('/')[1];
}
return `https://chromium.googlesource.com/chromium/src/+/${
revisionIdentifier}/${filepath}`;
}
// Client info
if (browserBridge.clientInfo) {
clientInfo = browserBridge.clientInfo;
this.setTable_('client-info', [
{description: 'Data exported', value: (new Date()).toISOString()},
{description: 'Chrome version', value: clientInfo.version},
{description: 'Operating system', value: clientInfo.operating_system},
{
description: 'Software rendering list URL',
value: createSourcePermalink(
clientInfo.revision_identifier,
'gpu/config/software_rendering_list.json'),
},
{
description: 'Driver bug list URL',
value: createSourcePermalink(
clientInfo.revision_identifier,
'gpu/config/gpu_driver_bug_list.json'),
},
{description: 'ANGLE commit id', value: clientInfo.angle_commit_id},
{
description: '2D graphics backend',
value: clientInfo.graphics_backend,
},
{description: 'Command Line', value: clientInfo.command_line},
]);
} else {
this.setText_('client-info', '... loading...');
}
// GPU info, basic
const diagnosticsDiv = this.shadowRoot.querySelector('.diagnostics');
const diagnosticsLoadingDiv =
this.shadowRoot.querySelector('.diagnostics-loading');
const featureStatusList =
this.shadowRoot.querySelector('.feature-status-list');
const problemsDiv = this.shadowRoot.querySelector('.problems-div');
const problemsList = this.shadowRoot.querySelector('.problems-list');
const workaroundsDiv = this.shadowRoot.querySelector('.workarounds-div');
const workaroundsList = this.shadowRoot.querySelector('.workarounds-list');
const ANGLEFeaturesDiv =
this.shadowRoot.querySelector('.angle-features-div');
const ANGLEFeaturesList =
this.shadowRoot.querySelector('.angle-features-list');
const DAWNInfoDiv = this.shadowRoot.querySelector('.dawn-info-div');
const DAWNInfoList = this.shadowRoot.querySelector('.dawn-info-list');
const basicInfoForHardwareGpuDiv =
this.shadowRoot.querySelector('.basic-info-for-hardware-gpu-div');
const featureStatusForHardwareGpuDiv =
this.shadowRoot.querySelector('.feature-status-for-hardware-gpu-div');
const featureStatusForHardwareGpuList =
this.shadowRoot.querySelector('.feature-status-for-hardware-gpu-list');
const problemsForHardwareGpuDiv =
this.shadowRoot.querySelector('.problems-for-hardware-gpu-div');
const problemsForHardwareGpuList =
this.shadowRoot.querySelector('.problems-for-hardware-gpu-list');
const workaroundsForHardwareGpuDiv =
this.shadowRoot.querySelector('.workarounds-for-hardware-gpu-div');
const workaroundsForHardwareGpuList =
this.shadowRoot.querySelector('.workarounds-for-hardware-gpu-list');
const gpuInfo = browserBridge.gpuInfo;
let i;
if (gpuInfo) {
// Not using jstemplate here for blocklist status because we construct
// href from data, which jstemplate can't seem to do.
if (gpuInfo.featureStatus) {
this.appendFeatureInfo_(
gpuInfo.featureStatus, featureStatusList, problemsDiv, problemsList,
workaroundsDiv, workaroundsList);
} else {
featureStatusList.textContent = '';
problemsList.hidden = true;
workaroundsList.hidden = true;
}
if (gpuInfo.featureStatusForHardwareGpu) {
basicInfoForHardwareGpuDiv.hidden = false;
featureStatusForHardwareGpuDiv.hidden = false;
problemsForHardwareGpuDiv.hidden = false;
workaroundsForHardwareGpuDiv.hidden = false;
this.appendFeatureInfo_(
gpuInfo.featureStatusForHardwareGpu,
featureStatusForHardwareGpuList, problemsForHardwareGpuDiv,
problemsForHardwareGpuList, workaroundsForHardwareGpuDiv,
workaroundsForHardwareGpuList);
if (gpuInfo.basicInfoForHardwareGpu) {
this.setTable_(
'basic-info-for-hardware-gpu', gpuInfo.basicInfoForHardwareGpu);
} else {
this.setTable_('basic-info-for-hardware-gpu', []);
}
} else {
basicInfoForHardwareGpuDiv.hidden = true;
featureStatusForHardwareGpuDiv.hidden = true;
problemsForHardwareGpuDiv.hidden = true;
workaroundsForHardwareGpuDiv.hidden = true;
}
if (gpuInfo.basicInfo) {
this.setTable_('basic-info', gpuInfo.basicInfo);
} else {
this.setTable_('basic-info', []);
}
if (gpuInfo.compositorInfo) {
this.setTable_('compositor-info', gpuInfo.compositorInfo);
} else {
this.setTable_('compositor-info', []);
}
if (gpuInfo.gpuMemoryBufferInfo) {
this.setTable_('gpu-memory-buffer-info', gpuInfo.gpuMemoryBufferInfo);
} else {
this.setTable_('gpu-memory-buffer-info', []);
}
if (gpuInfo.displayInfo) {
this.setTable_('display-info', gpuInfo.displayInfo);
} else {
this.setTable_('display-info', []);
}
if (gpuInfo.videoAcceleratorsInfo) {
this.setTable_(
'video-acceleration-info', gpuInfo.videoAcceleratorsInfo);
} else {
this.setTable_('video-acceleration-info', []);
}
if (gpuInfo.ANGLEFeatures) {
if (gpuInfo.ANGLEFeatures.length) {
ANGLEFeaturesDiv.hidden = false;
ANGLEFeaturesList.textContent = '';
for (const ANGLEFeature of gpuInfo.ANGLEFeatures) {
const ANGLEFeatureEl = this.createANGLEFeatureEl_(ANGLEFeature);
ANGLEFeaturesList.appendChild(ANGLEFeatureEl);
}
} else {
ANGLEFeaturesDiv.hidden = true;
}
}
if (gpuInfo.dawnInfo) {
if (gpuInfo.dawnInfo.length) {
DAWNInfoDiv.hidden = false;
this.createDawnInfoEl_(DAWNInfoList, gpuInfo.dawnInfo);
} else {
DAWNInfoDiv.hidden = true;
}
}
if (gpuInfo.diagnostics) {
diagnosticsDiv.hidden = false;
diagnosticsLoadingDiv.hidden = true;
this.shadowRoot.querySelector('#diagnostics-table').hidden = false;
this.setTable_('diagnostics-table', gpuInfo.diagnostics);
} else if (gpuInfo.diagnostics === null) {
// gpu_internals.cc sets diagnostics to null when it is being loaded
diagnosticsDiv.hidden = false;
diagnosticsLoadingDiv.hidden = false;
this.shadowRoot.querySelector('#diagnostics-table').hidden = true;
} else {
diagnosticsDiv.hidden = true;
}
if (gpuInfo.vulkanInfo) {
const vulkanInfo = new VulkanInfo(gpuInfo.vulkanInfo);
const data = [{
'description': 'info',
'value': vulkanInfo.toString(),
'id': 'vulkan-info-value',
}];
this.setTable_('vulkan-info', data);
} else {
this.setTable_('vulkan-info', []);
}
if (gpuInfo.devicePerfInfo) {
this.setTable_('device-perf-info', gpuInfo.devicePerfInfo);
} else {
this.setTable_('device-perf-info', []);
}
} else {
this.setText_('basic-info', '... loading ...');
diagnosticsDiv.hidden = true;
featureStatusList.textContent = '';
problemsDiv.hidden = true;
DAWNInfoDiv.hidden = true;
}
// Log messages
const messageList = this.shadowRoot.querySelector('#log-messages > ul');
messageList.innerHTML =
window.trustedTypes ? window.trustedTypes.emptyHTML : '';
browserBridge.logMessages.forEach(messageObj => {
const messageEl = document.createElement('span');
messageEl.textContent = `${messageObj.header}: ${messageObj.message}`;
const li = document.createElement('li');
li.appendChild(messageEl);
messageList.appendChild(li);
});
}
可以看到,一处位于以下代码片段:
// Not using jstemplate here for blocklist status because we construct
// href from data, which jstemplate can't seem to do.
if (gpuInfo.featureStatus) {
this.appendFeatureInfo_(
gpuInfo.featureStatus, featureStatusList, problemsDiv, problemsList,
workaroundsDiv, workaroundsList);
} else {
featureStatusList.textContent = '';
problemsList.hidden = true;
workaroundsList.hidden = true;
}
另一处在以下代码片段中:
if (gpuInfo.featureStatusForHardwareGpu) {
basicInfoForHardwareGpuDiv.hidden = false;
featureStatusForHardwareGpuDiv.hidden = false;
problemsForHardwareGpuDiv.hidden = false;
workaroundsForHardwareGpuDiv.hidden = false;
this.appendFeatureInfo_(
gpuInfo.featureStatusForHardwareGpu,
featureStatusForHardwareGpuList, problemsForHardwareGpuDiv,
problemsForHardwareGpuList, workaroundsForHardwareGpuDiv,
workaroundsForHardwareGpuList);
if (gpuInfo.basicInfoForHardwareGpu) {
this.setTable_(
'basic-info-for-hardware-gpu', gpuInfo.basicInfoForHardwareGpu);
} else {
this.setTable_('basic-info-for-hardware-gpu', []);
}
} else {
basicInfoForHardwareGpuDiv.hidden = true;
featureStatusForHardwareGpuDiv.hidden = true;
problemsForHardwareGpuDiv.hidden = true;
workaroundsForHardwareGpuDiv.hidden = true;
}
来看一下这两处调用传递给appendFeatureInfo_函数的实参分别是什么:
this.appendFeatureInfo_(
gpuInfo.featureStatus, featureStatusList, problemsDiv, problemsList,
workaroundsDiv, workaroundsList);
appendFeatureInfo_(
featureInfo, featureStatusList, problemsDiv, problemsList, workaroundsDiv,
workaroundsList)
实参 ---> 形参
gpuInfo.featureStatus ---> featureInfo
featureStatusList ---> featureStatusList
problemsDiv ---> problemsDiv
problemsList ---> problemsList
workaroundsDiv ---> workaroundsDiv
workaroundsList ---> workaroundsList
this.appendFeatureInfo_(
gpuInfo.featureStatusForHardwareGpu,
featureStatusForHardwareGpuList, problemsForHardwareGpuDiv,
problemsForHardwareGpuList, workaroundsForHardwareGpuDiv,
workaroundsForHardwareGpuList);
appendFeatureInfo_(
featureInfo, featureStatusList, problemsDiv, problemsList, workaroundsDiv,
workaroundsList)
实参 ---> 形参
gpuInfo.featureStatusForHardwareGpu ---> featureInfo
featureStatusForHardwareGpuList ---> featureStatusList
problemsForHardwareGpuDiv ---> problemsDiv
problemsForHardwareGpuList ---> problemsList
workaroundsForHardwareGpuDiv ---> workaroundsDiv
workaroundsForHardwareGpuList ---> workaroundsList
甭管是第一处调用还是第二处调用,都与gpuInfo有关。gpuInfo又是由browserBridge.gpuInfo得到,代码如下:
const gpuInfo = browserBridge.gpuInfo;
因此,这个browserBridge.gpuInfo就是揭开谜题、揭开内幕的钥匙。
欲知后事如何,且看下回分解。