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

 评论