1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gpu/ipc/in_process_gpu_thread_holder.h"
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread_task_runner_handle.h"
12 #include "build/build_config.h"
13 #include "gpu/command_buffer/service/mailbox_manager_factory.h"
14 #include "gpu/command_buffer/service/scheduler.h"
15 #include "gpu/command_buffer/service/service_utils.h"
16 #include "gpu/command_buffer/service/shared_image_manager.h"
17 #include "gpu/command_buffer/service/sync_point_manager.h"
18 #include "gpu/config/gpu_info_collector.h"
19 #include "gpu/config/gpu_util.h"
20 #include "ui/gl/init/gl_factory.h"
21 
22 namespace gpu {
23 
InProcessGpuThreadHolder()24 InProcessGpuThreadHolder::InProcessGpuThreadHolder()
25     : base::Thread("GpuThread") {
26   DCHECK(base::CommandLine::InitializedForCurrentProcess());
27   auto* command_line = base::CommandLine::ForCurrentProcess();
28   gpu_preferences_ = gles2::ParseGpuPreferences(command_line);
29 
30   gpu::GPUInfo gpu_info;
31   gpu::CollectGraphicsInfoForTesting(&gpu_info);
32   gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(gpu_info, gpu_preferences_,
33                                                  command_line, nullptr);
34 
35   Start();
36 }
37 
~InProcessGpuThreadHolder()38 InProcessGpuThreadHolder::~InProcessGpuThreadHolder() {
39   // Ensure members created on GPU thread are destroyed there too.
40   task_runner()->PostTask(
41       FROM_HERE, base::BindOnce(&InProcessGpuThreadHolder::DeleteOnGpuThread,
42                                 base::Unretained(this)));
43   Stop();
44 }
45 
GetGpuPreferences()46 GpuPreferences* InProcessGpuThreadHolder::GetGpuPreferences() {
47   DCHECK(!task_executor_);
48   return &gpu_preferences_;
49 }
50 
GetGpuFeatureInfo()51 GpuFeatureInfo* InProcessGpuThreadHolder::GetGpuFeatureInfo() {
52   DCHECK(!task_executor_);
53   return &gpu_feature_info_;
54 }
55 
GetTaskExecutor()56 CommandBufferTaskExecutor* InProcessGpuThreadHolder::GetTaskExecutor() {
57   if (!task_executor_) {
58     base::WaitableEvent completion;
59     task_runner()->PostTask(
60         FROM_HERE,
61         base::BindOnce(&InProcessGpuThreadHolder::InitializeOnGpuThread,
62                        base::Unretained(this), &completion));
63     completion.Wait();
64   }
65   return task_executor_.get();
66 }
67 
InitializeOnGpuThread(base::WaitableEvent * completion)68 void InProcessGpuThreadHolder::InitializeOnGpuThread(
69     base::WaitableEvent* completion) {
70   sync_point_manager_ = std::make_unique<SyncPointManager>();
71   scheduler_ = std::make_unique<Scheduler>(
72       task_runner(), sync_point_manager_.get(), gpu_preferences_);
73   mailbox_manager_ = gles2::CreateMailboxManager(gpu_preferences_);
74   shared_image_manager_ = std::make_unique<SharedImageManager>();
75 
76   share_group_ = new gl::GLShareGroup();
77   surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
78   gl::GLContextAttribs attribs = gles2::GenerateGLContextAttribs(
79       ContextCreationAttribs(), false /* use_passthrough_decoder */);
80   context_ =
81       gl::init::CreateGLContext(share_group_.get(), surface_.get(), attribs);
82   CHECK(context_->MakeCurrent(surface_.get()));
83   GpuDriverBugWorkarounds gpu_driver_bug_workarounds(
84       gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
85 
86   bool use_virtualized_gl_context_ = false;
87 #if defined(OS_MACOSX)
88   // Virtualize GpuPreference:::kLowPower contexts by default on OS X to prevent
89   // performance regressions when enabling FCM. https://crbug.com/180463
90   use_virtualized_gl_context_ = true;
91 #endif
92   use_virtualized_gl_context_ |=
93       gpu_driver_bug_workarounds.use_virtualized_gl_contexts;
94 
95   context_state_ = base::MakeRefCounted<SharedContextState>(
96       share_group_, surface_, context_, use_virtualized_gl_context_,
97       base::DoNothing(), gpu_preferences_.gr_context_type);
98   auto feature_info = base::MakeRefCounted<gles2::FeatureInfo>(
99       gpu_driver_bug_workarounds, gpu_feature_info_);
100   context_state_->InitializeGL(gpu_preferences_, feature_info);
101   context_state_->InitializeGrContext(gpu_preferences_,
102                                       gpu_driver_bug_workarounds, nullptr);
103 
104   task_executor_ = std::make_unique<GpuInProcessThreadService>(
105       this, task_runner(), scheduler_.get(), sync_point_manager_.get(),
106       mailbox_manager_.get(), gl::GLSurfaceFormat(), gpu_feature_info_,
107       gpu_preferences_, shared_image_manager_.get(), nullptr);
108 
109   completion->Signal();
110 }
111 
DeleteOnGpuThread()112 void InProcessGpuThreadHolder::DeleteOnGpuThread() {
113   task_executor_.reset();
114   scheduler_.reset();
115   sync_point_manager_.reset();
116   shared_image_manager_.reset();
117 
118   context_state_.reset();
119   context_.reset();
120   surface_.reset();
121   share_group_.reset();
122 }
123 
124 scoped_refptr<SharedContextState>
GetSharedContextState()125 InProcessGpuThreadHolder::GetSharedContextState() {
126   DCHECK(context_state_);
127   return context_state_;
128 }
129 
GetShareGroup()130 scoped_refptr<gl::GLShareGroup> InProcessGpuThreadHolder::GetShareGroup() {
131   if (!share_group_)
132     share_group_ = base::MakeRefCounted<gl::GLShareGroup>();
133   return share_group_;
134 }
135 
136 }  // namespace gpu
137