OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "content/common/gpu/gpu_channel_manager.h" | |
6 | |
7 #include <algorithm> | |
8 #include <utility> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/location.h" | |
12 #include "base/single_thread_task_runner.h" | |
13 #include "base/thread_task_runner_handle.h" | |
14 #include "build/build_config.h" | |
15 #include "content/common/gpu/gpu_channel.h" | |
16 #include "content/common/gpu/gpu_channel_manager_delegate.h" | |
17 #include "content/common/gpu/gpu_memory_buffer_factory.h" | |
18 #include "content/common/gpu/gpu_memory_manager.h" | |
19 #include "gpu/command_buffer/common/sync_token.h" | |
20 #include "gpu/command_buffer/common/value_state.h" | |
21 #include "gpu/command_buffer/service/feature_info.h" | |
22 #include "gpu/command_buffer/service/mailbox_manager.h" | |
23 #include "gpu/command_buffer/service/memory_program_cache.h" | |
24 #include "gpu/command_buffer/service/shader_translator_cache.h" | |
25 #include "gpu/command_buffer/service/sync_point_manager.h" | |
26 #include "gpu/ipc/common/gpu_messages.h" | |
27 #include "ui/gl/gl_bindings.h" | |
28 #include "ui/gl/gl_share_group.h" | |
29 | |
30 namespace content { | |
31 | |
32 namespace { | |
33 #if defined(OS_ANDROID) | |
34 // Amount of time we expect the GPU to stay powered up without being used. | |
35 const int kMaxGpuIdleTimeMs = 40; | |
36 // Maximum amount of time we keep pinging the GPU waiting for the client to | |
37 // draw. | |
38 const int kMaxKeepAliveTimeMs = 200; | |
39 #endif | |
40 | |
41 } | |
42 | |
43 GpuChannelManager::GpuChannelManager( | |
44 const gpu::GpuPreferences& gpu_preferences, | |
45 GpuChannelManagerDelegate* delegate, | |
46 GpuWatchdog* watchdog, | |
47 base::SingleThreadTaskRunner* task_runner, | |
48 base::SingleThreadTaskRunner* io_task_runner, | |
49 base::WaitableEvent* shutdown_event, | |
50 gpu::SyncPointManager* sync_point_manager, | |
51 GpuMemoryBufferFactory* gpu_memory_buffer_factory) | |
52 : task_runner_(task_runner), | |
53 io_task_runner_(io_task_runner), | |
54 gpu_preferences_(gpu_preferences), | |
55 delegate_(delegate), | |
56 watchdog_(watchdog), | |
57 shutdown_event_(shutdown_event), | |
58 share_group_(new gfx::GLShareGroup), | |
59 mailbox_manager_(gpu::gles2::MailboxManager::Create(gpu_preferences)), | |
60 gpu_memory_manager_(this), | |
61 sync_point_manager_(sync_point_manager), | |
62 sync_point_client_waiter_( | |
63 sync_point_manager->CreateSyncPointClientWaiter()), | |
64 gpu_memory_buffer_factory_(gpu_memory_buffer_factory), | |
65 weak_factory_(this) { | |
66 DCHECK(task_runner); | |
67 DCHECK(io_task_runner); | |
68 if (gpu_preferences_.ui_prioritize_in_gpu_process) | |
69 preemption_flag_ = new gpu::PreemptionFlag; | |
70 } | |
71 | |
72 GpuChannelManager::~GpuChannelManager() { | |
73 // Destroy channels before anything else because of dependencies. | |
74 gpu_channels_.clear(); | |
75 if (default_offscreen_surface_.get()) { | |
76 default_offscreen_surface_->Destroy(); | |
77 default_offscreen_surface_ = NULL; | |
78 } | |
79 } | |
80 | |
81 gpu::gles2::ProgramCache* GpuChannelManager::program_cache() { | |
82 if (!program_cache_.get() && | |
83 (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary || | |
84 gfx::g_driver_gl.ext.b_GL_OES_get_program_binary) && | |
85 !gpu_preferences_.disable_gpu_program_cache) { | |
86 program_cache_.reset(new gpu::gles2::MemoryProgramCache( | |
87 gpu_preferences_.gpu_program_cache_size, | |
88 gpu_preferences_.disable_gpu_shader_disk_cache)); | |
89 } | |
90 return program_cache_.get(); | |
91 } | |
92 | |
93 gpu::gles2::ShaderTranslatorCache* | |
94 GpuChannelManager::shader_translator_cache() { | |
95 if (!shader_translator_cache_.get()) { | |
96 shader_translator_cache_ = | |
97 new gpu::gles2::ShaderTranslatorCache(gpu_preferences_); | |
98 } | |
99 return shader_translator_cache_.get(); | |
100 } | |
101 | |
102 gpu::gles2::FramebufferCompletenessCache* | |
103 GpuChannelManager::framebuffer_completeness_cache() { | |
104 if (!framebuffer_completeness_cache_.get()) | |
105 framebuffer_completeness_cache_ = | |
106 new gpu::gles2::FramebufferCompletenessCache; | |
107 return framebuffer_completeness_cache_.get(); | |
108 } | |
109 | |
110 void GpuChannelManager::RemoveChannel(int client_id) { | |
111 delegate_->DidDestroyChannel(client_id); | |
112 gpu_channels_.erase(client_id); | |
113 } | |
114 | |
115 #if defined(OS_MACOSX) | |
116 void GpuChannelManager::AddBufferPresentedCallback( | |
117 int32_t surface_id, | |
118 const BufferPresentedCallback& callback) { | |
119 DCHECK(buffer_presented_callback_map_.find(surface_id) == | |
120 buffer_presented_callback_map_.end()); | |
121 buffer_presented_callback_map_[surface_id] = callback; | |
122 } | |
123 | |
124 void GpuChannelManager::RemoveBufferPresentedCallback(int32_t surface_id) { | |
125 auto it = buffer_presented_callback_map_.find(surface_id); | |
126 DCHECK(it != buffer_presented_callback_map_.end()); | |
127 buffer_presented_callback_map_.erase(it); | |
128 } | |
129 | |
130 void GpuChannelManager::BufferPresented(int32_t surface_id, | |
131 const base::TimeTicks& vsync_timebase, | |
132 const base::TimeDelta& vsync_interval) { | |
133 auto it = buffer_presented_callback_map_.find(surface_id); | |
134 if (it != buffer_presented_callback_map_.end()) | |
135 it->second.Run(surface_id, vsync_timebase, vsync_interval); | |
136 } | |
137 #endif | |
138 | |
139 GpuChannel* GpuChannelManager::LookupChannel(int32_t client_id) const { | |
140 const auto& it = gpu_channels_.find(client_id); | |
141 return it != gpu_channels_.end() ? it->second : nullptr; | |
142 } | |
143 | |
144 scoped_ptr<GpuChannel> GpuChannelManager::CreateGpuChannel( | |
145 int client_id, | |
146 uint64_t client_tracing_id, | |
147 bool preempts, | |
148 bool allow_view_command_buffers, | |
149 bool allow_real_time_streams) { | |
150 return make_scoped_ptr( | |
151 new GpuChannel(this, sync_point_manager(), watchdog_, share_group(), | |
152 mailbox_manager(), preempts ? preemption_flag() : nullptr, | |
153 preempts ? nullptr : preemption_flag(), task_runner_.get(), | |
154 io_task_runner_.get(), client_id, client_tracing_id, | |
155 allow_view_command_buffers, allow_real_time_streams)); | |
156 } | |
157 | |
158 IPC::ChannelHandle GpuChannelManager::EstablishChannel( | |
159 int client_id, | |
160 uint64_t client_tracing_id, | |
161 bool preempts, | |
162 bool allow_view_command_buffers, | |
163 bool allow_real_time_streams) { | |
164 scoped_ptr<GpuChannel> channel( | |
165 CreateGpuChannel(client_id, client_tracing_id, preempts, | |
166 allow_view_command_buffers, allow_real_time_streams)); | |
167 IPC::ChannelHandle channel_handle = channel->Init(shutdown_event_); | |
168 gpu_channels_.set(client_id, std::move(channel)); | |
169 return channel_handle; | |
170 } | |
171 | |
172 void GpuChannelManager::InternalDestroyGpuMemoryBuffer( | |
173 gfx::GpuMemoryBufferId id, | |
174 int client_id) { | |
175 io_task_runner_->PostTask( | |
176 FROM_HERE, | |
177 base::Bind(&GpuChannelManager::InternalDestroyGpuMemoryBufferOnIO, | |
178 base::Unretained(this), id, client_id)); | |
179 } | |
180 | |
181 void GpuChannelManager::InternalDestroyGpuMemoryBufferOnIO( | |
182 gfx::GpuMemoryBufferId id, | |
183 int client_id) { | |
184 gpu_memory_buffer_factory_->DestroyGpuMemoryBuffer(id, client_id); | |
185 } | |
186 | |
187 void GpuChannelManager::DestroyGpuMemoryBuffer( | |
188 gfx::GpuMemoryBufferId id, | |
189 int client_id, | |
190 const gpu::SyncToken& sync_token) { | |
191 if (sync_token.HasData()) { | |
192 scoped_refptr<gpu::SyncPointClientState> release_state = | |
193 sync_point_manager()->GetSyncPointClientState( | |
194 sync_token.namespace_id(), sync_token.command_buffer_id()); | |
195 if (release_state) { | |
196 sync_point_client_waiter_->WaitOutOfOrder( | |
197 release_state.get(), sync_token.release_count(), | |
198 base::Bind(&GpuChannelManager::InternalDestroyGpuMemoryBuffer, | |
199 base::Unretained(this), id, client_id)); | |
200 return; | |
201 } | |
202 } | |
203 | |
204 // No sync token or invalid sync token, destroy immediately. | |
205 InternalDestroyGpuMemoryBuffer(id, client_id); | |
206 } | |
207 | |
208 void GpuChannelManager::UpdateValueState(int client_id, | |
209 unsigned int target, | |
210 const gpu::ValueState& state) { | |
211 // Only pass updated state to the channel corresponding to the | |
212 // render_widget_host where the event originated. | |
213 auto it = gpu_channels_.find(client_id); | |
214 if (it != gpu_channels_.end()) | |
215 it->second->HandleUpdateValueState(target, state); | |
216 } | |
217 | |
218 void GpuChannelManager::PopulateShaderCache(const std::string& program_proto) { | |
219 if (program_cache()) | |
220 program_cache()->LoadProgram(program_proto); | |
221 } | |
222 | |
223 uint32_t GpuChannelManager::GetUnprocessedOrderNum() const { | |
224 uint32_t unprocessed_order_num = 0; | |
225 for (auto& kv : gpu_channels_) { | |
226 unprocessed_order_num = | |
227 std::max(unprocessed_order_num, kv.second->GetUnprocessedOrderNum()); | |
228 } | |
229 return unprocessed_order_num; | |
230 } | |
231 | |
232 uint32_t GpuChannelManager::GetProcessedOrderNum() const { | |
233 uint32_t processed_order_num = 0; | |
234 for (auto& kv : gpu_channels_) { | |
235 processed_order_num = | |
236 std::max(processed_order_num, kv.second->GetProcessedOrderNum()); | |
237 } | |
238 return processed_order_num; | |
239 } | |
240 | |
241 void GpuChannelManager::LoseAllContexts() { | |
242 for (auto& kv : gpu_channels_) { | |
243 kv.second->MarkAllContextsLost(); | |
244 } | |
245 task_runner_->PostTask(FROM_HERE, | |
246 base::Bind(&GpuChannelManager::DestroyAllChannels, | |
247 weak_factory_.GetWeakPtr())); | |
248 } | |
249 | |
250 void GpuChannelManager::DestroyAllChannels() { | |
251 gpu_channels_.clear(); | |
252 } | |
253 | |
254 gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() { | |
255 if (!default_offscreen_surface_.get()) { | |
256 default_offscreen_surface_ = | |
257 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size()); | |
258 } | |
259 return default_offscreen_surface_.get(); | |
260 } | |
261 | |
262 #if defined(OS_ANDROID) | |
263 void GpuChannelManager::DidAccessGpu() { | |
264 last_gpu_access_time_ = base::TimeTicks::Now(); | |
265 } | |
266 | |
267 void GpuChannelManager::WakeUpGpu() { | |
268 begin_wake_up_time_ = base::TimeTicks::Now(); | |
269 ScheduleWakeUpGpu(); | |
270 } | |
271 | |
272 void GpuChannelManager::ScheduleWakeUpGpu() { | |
273 base::TimeTicks now = base::TimeTicks::Now(); | |
274 TRACE_EVENT2("gpu", "GpuChannelManager::ScheduleWakeUp", | |
275 "idle_time", (now - last_gpu_access_time_).InMilliseconds(), | |
276 "keep_awake_time", (now - begin_wake_up_time_).InMilliseconds()); | |
277 if (now - last_gpu_access_time_ < | |
278 base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs)) | |
279 return; | |
280 if (now - begin_wake_up_time_ > | |
281 base::TimeDelta::FromMilliseconds(kMaxKeepAliveTimeMs)) | |
282 return; | |
283 | |
284 DoWakeUpGpu(); | |
285 | |
286 base::MessageLoop::current()->PostDelayedTask( | |
287 FROM_HERE, base::Bind(&GpuChannelManager::ScheduleWakeUpGpu, | |
288 weak_factory_.GetWeakPtr()), | |
289 base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs)); | |
290 } | |
291 | |
292 void GpuChannelManager::DoWakeUpGpu() { | |
293 const GpuCommandBufferStub* stub = nullptr; | |
294 for (const auto& kv : gpu_channels_) { | |
295 const GpuChannel* channel = kv.second; | |
296 stub = channel->GetOneStub(); | |
297 if (stub) { | |
298 DCHECK(stub->decoder()); | |
299 break; | |
300 } | |
301 } | |
302 if (!stub || !stub->decoder()->MakeCurrent()) | |
303 return; | |
304 glFinish(); | |
305 DidAccessGpu(); | |
306 } | |
307 #endif | |
308 | |
309 } // namespace content | |
OLD | NEW |