Graphics3D用不了
在PPAPI的example中,想要去run这个demo,发现run不起来:
- ppapi/example/gles2_spinning_cube
跟踪原因:
- gles2_spinning_cube.cc中,初始化DemoInstance的函数里,有报错:
void DemoInstance::InitGL(int32_t /*result*/) { assert(plugin_size_.width() && plugin_size_.height()); if (context_) { context_->ResizeBuffers(plugin_size_.width(), plugin_size_.height()); return; } int32_t context_attributes[] = { PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8, PP_GRAPHICS3DATTRIB_RED_SIZE, 8, PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0, PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0, PP_GRAPHICS3DATTRIB_SAMPLES, 0, PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, PP_GRAPHICS3DATTRIB_WIDTH, plugin_size_.width(), PP_GRAPHICS3DATTRIB_HEIGHT, plugin_size_.height(), PP_GRAPHICS3DATTRIB_NONE, }; context_ = new pp::Graphics3D(this, context_attributes); assert(!context_->is_null());//关键在这里,new Graphics3D,得到一个null的context //也就是说,Graphics3D不可用 assert(BindGraphics(*context_)); glSetCurrentContextPPAPI(context_->pp_resource()); cube_.Init(plugin_size_.width(), plugin_size_.height()); Paint(PP_OK); }
追踪原因:
ppapi/cpp/graphics_3d.h
- Graphics3D,在ppapi/cpp/graphics_3d.h中定义
- ppapi/cpp/graphics_3d.cc中,的构造函数如下:
Graphics3D::Graphics3D() {
}
Graphics3D::Graphics3D(const InstanceHandle& instance,
const int32_t attrib_list[]) {
if (has_interface<PPB_Graphics3D_1_0>()) {
PassRefFromConstructor(get_interface<PPB_Graphics3D_1_0>()->Create(
instance.pp_instance(), 0, attrib_list));
}
}
Graphics3D::Graphics3D(const InstanceHandle& instance,
const Graphics3D& share_context,
const int32_t attrib_list[]) {
if (has_interface<PPB_Graphics3D_1_0>()) {
PassRefFromConstructor(get_interface<PPB_Graphics3D_1_0>()->Create(
instance.pp_instance(),
share_context.pp_resource(),
attrib_list));
}
}
- 在这里面,Graphics3D实际指向的interface,应该是PPB_Graphics3D_1_0
ppapi/c/ppb_graphics_3d.h
- 这个是头文件定义的很多接口,比如create等
- 实际实现是:content/renderer/pepper/ppb_graphics_3d_impl.cc
content/renderer/pepper/ppb_graphics_3d_impl.cc
- ppapi/c/ppb_graphics_3d.h中的create接口,实际实现是:
PP_Resource PPB_Graphics4D_Impl::CreateRaw(
PP_Instance instance,
PP_Resource share_context,
const ppapi::Graphics3DContextAttribs& context_attribs,
gpu::Capabilities* capabilities,
gpu::GLCapabilities* gl_capabilities,
const base::UnsafeSharedMemoryRegion** shared_state_region,
gpu::CommandBufferId* command_buffer_id) {
PPB_Graphics3D_API* share_api = nullptr;
if (share_context) {
EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
if (enter.failed())
return 0;
share_api = enter.object();
}
scoped_refptr<PPB_Graphics3D_Impl> graphics_3d(
new PPB_Graphics3D_Impl(instance));
if (!graphics_3d->InitRaw(share_api, context_attribs, capabilities,
gl_capabilities, shared_state_region,
command_buffer_id)) {
//主要是这里,如果InitRaw不成功,就return 0,否则return真是创建好的graphics_3d对象
return 0;
}
return graphics_3d->GetReference();
}
- 在看InitRaw函数:
bool PPB_Graphics3D_Impl::InitRaw(
PPB_Graphics3D_API* share_context,
const ppapi::Graphics3DContextAttribs& requested_attribs,
gpu::Capabilities* capabilities,
gpu::GLCapabilities* gl_capabilities,
const base::UnsafeSharedMemoryRegion** shared_state_region,
gpu::CommandBufferId* command_buffer_id) {
//函数很长,我做了省略,主要问题在这里
//render_thread的IsGpuCompositingDisabled(),return true了。
//相当于没有打开GPU合成的功能。
...
VLOG(1) << "ryanhuen InitRaw call.6 "<<render_thread->IsGpuCompositingDisabled();
if (render_thread->IsGpuCompositingDisabled())
return false;
...
return true;
}
render_thread→IsGpuCompositingDisabled())
- render_thread是谁?
- 看这个变量,有两个实现:
- content/public/renderer/render_thread.cc
- content/renderer/render_thread_impl.cc
- 但是实际上,存在IsGpuCompositingDisabled()函数的,只有:
- ./content/renderer/render_thread_impl.h
- 所以,肯定是content/renderer/render_thread_impl.cc了。
- 看这个变量,有两个实现:
- 当然,IsGpuCompositingDisabled()指向的是is_gpu_compositing_disabled_这个变量。
- 那就得看is_gpu_compositing_disabled_到底是怎么变成true的。
is_gpu_compositing_disabled_
is_gpu_compositing_disabled_ = true 只有两个地方调用,都在content/renderer/render_thread_impl.cc中
- void RenderThreadImpl::Init() 函数中
- RenderThreadImpl::CompositingModeFallbackToSoftware()函数中
void RenderThreadImpl::Init()中,如下:
// kDisableGpuCompositing 对应 --disable-gpu-compositing if (command_line.HasSwitch(switches::kDisableGpuCompositing)) is_gpu_compositing_disabled_ = true; //我们在启动开关里,没有配置过kDisableGpuCompositing //因此不是这里
RenderThreadImpl::CompositingModeFallbackToSoftware()
那就看谁调用了这个函数了。
上堆栈:
[52624:1:1212/152535.670678:VERBOSE1:render_thread_impl.cc(1418)] ryanhuen RenderThreadImpl::CompositingModeFallbackToSoftware() [52625:1:1212/152535.859349:VERBOSE1:logging.cc(701)] [../../content/renderer/render_thread_impl.cc(1418)]call stack is : #0 0x7ff3ed56316c base::debug::CollectStackTrace() #1 0x7ff3ed5136ea base::debug::StackTrace::StackTrace() #2 0x7ff3ed5136a5 base::debug::StackTrace::StackTrace() #3 0x7ff3ed23337f logging::LogMessage::LogMessage() #4 0x7ff3e6c1e3d8 content::RenderThreadImpl::CompositingModeFallbackToSoftware() #5 0x7ff3e3760643 viz::mojom::CompositingModeWatcherStubDispatch::Accept() #6 0x7ff3e6c278b0 viz::mojom::CompositingModeWatcherStub<>::Accept(
到这里,链路其实断了。因为这个函数明显看到,是mojo的通信,也就是说,这个函数,应该是跨进程的消息调用,render_thread只是被动的被通知,gpu compositing disabled了。
看看还有谁is_gpu_compositing_disabled_ = true
全局搜索: “is_gpu_compositing_disabled_ = true”
content/browser/compositor/viz_process_transport_factory.cc:
结果让我无意中发现:
- content/browser/compositor/viz_process_transport_factory.cc
void VizProcessTransportFactory::DisableGpuCompositing( ui::Compositor* guilty_compositor) { is_gpu_compositing_disabled_ = true;//这个地方也禁用了gpu compositing // Change the result of GpuDataManagerImpl::IsGpuCompositingDisabled() before // notifying anything. GpuDataManagerImpl::GetInstance()->SetGpuCompositingDisabled(); //还通知Gpu data mananger compositing_mode_reporter_->SetUsingSoftwareCompositing(); //这个函数也很眼熟:看看下面我贴出来的 } components/viz/host/compositing_mode_reporter_impl.cc void CompositingModeReporterImpl::SetUsingSoftwareCompositing() { gpu_ = false; for (auto& it : watchers_) it->CompositingModeFallbackToSoftware(); //兜来兜去,原来是在这里,调用到了RenderThreadImpl的CompositingModeFallbackToSoftware()函数 }
- 那毫无疑问了,content/browser/compositor/viz_process_transport_factory.cc是关键
content/browser/compositor/viz_process_transport_factory.cc
- 上堆栈看了一下DisableGpuCompositing(compositor);的来源
void VizProcessTransportFactory::OnEstablishedGpuChannel( base::WeakPtr<ui::Compositor> compositor_weak_ptr, scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) { ui::Compositor* compositor = compositor_weak_ptr.get(); if (!compositor) return; bool gpu_compositing = !is_gpu_compositing_disabled_ && !compositor->force_software_compositor(); if (gpu_compositing) { auto context_result = TryCreateContextsForGpuCompositing(gpu_channel_host); if (context_result == gpu::ContextResult::kTransientFailure) { // Get a new GpuChannelHost and retry context creation. gpu_channel_establish_factory_->EstablishGpuChannel( base::BindOnce(&VizProcessTransportFactory::OnEstablishedGpuChannel, weak_ptr_factory_.GetWeakPtr(), compositor_weak_ptr)); return; } else if (gpu::IsFatalOrSurfaceFailure(context_result)) { //主要是这里,gpu::IsFatalOrSurfaceFailure(context_result) return true了 DisableGpuCompositing(compositor); gpu_compositing = false; } }
- 那就看gpu::IsFatalOrSurfaceFailure(context_result)为什么return true了
gpu::IsFatalOrSurfaceFailure(context_result)
bool IsFatalOrSurfaceFailure(ContextResult result) {
VLOG(1)<< "ryanhuen IsFatalOrSurfaceFailure ContextResult::kFatalFailure" << (result == ContextResult::kFatalFailure) << "result == ContextResult::kSurfaceFailure" << (result == ContextResult::kSurfaceFailure);
return result == ContextResult::kFatalFailure ||
result == ContextResult::kSurfaceFailure;
}
//打印了一下结果:
//[54082:54082:1212/153006.972795:VERBOSE1:context_result.cc(11)] ryanhuen IsFatalOrSurfaceFailure ContextResult::kFatalFailure1result == ContextResult::kSurfaceFailure0
//看来是result == ContextResult::kFatalFailure
//result 是 auto context_result = TryCreateContextsForGpuCompositing(gpu_channel_host);得出的
//那就得看看TryCreateContextsForGpuCompositing(gpu_channel_host)
TryCreateContextsForGpuCompositing(gpu_channel_host)
gpu::ContextResult
VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
...
const auto& gpu_feature_info = gpu_channel_host->gpu_feature_info();
// Fallback to software compositing if GPU compositing is blocklisted.
// TODO(rivr): For now assume that if GL is blocklisted, then Vulkan is
// also. Just check GL to see if GPU compositing is disabled.
auto gpu_compositing_status =
gpu_feature_info.status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_GL];
if (gpu_compositing_status != gpu::kGpuFeatureStatusEnabled)
return gpu::ContextResult::kFatalFailure;
// 返回gpu::ContextResult::kFatalFailure;的只有这一个地方,所以问题关键点在这里
// 打印了一下 gpu_compositing_status,数值是2
// 同时gpu::kGpuFeatureStatusEnabled是枚举,也就是说,看看gpu_compositing_status对应的枚举是什么就行
...
return gpu::ContextResult::kSuccess;
}
gpu/config/gpu_feature_info.h
- 枚举对应的是GpuFeatureStatus
enum GpuFeatureStatus {
kGpuFeatureStatusEnabled, //0
kGpuFeatureStatusBlocklisted, //1
kGpuFeatureStatusDisabled, //2
kGpuFeatureStatusSoftware,
kGpuFeatureStatusUndefined,
kGpuFeatureStatusMax
};
- 所以,命中的是gpu::kGpuFeatureStatusDisabled