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 #ifndef CONTENT_COMMON_GPU_GPU_CHANNEL_H_ | |
6 #define CONTENT_COMMON_GPU_GPU_CHANNEL_H_ | |
7 | |
8 #include <stddef.h> | |
9 #include <stdint.h> | |
10 | |
11 #include <string> | |
12 | |
13 #include "base/containers/hash_tables.h" | |
14 #include "base/containers/scoped_ptr_hash_map.h" | |
15 #include "base/macros.h" | |
16 #include "base/memory/ref_counted.h" | |
17 #include "base/memory/scoped_ptr.h" | |
18 #include "base/memory/weak_ptr.h" | |
19 #include "base/process/process.h" | |
20 #include "base/threading/thread_checker.h" | |
21 #include "base/trace_event/memory_dump_provider.h" | |
22 #include "build/build_config.h" | |
23 #include "content/common/content_export.h" | |
24 #include "content/common/gpu/gpu_command_buffer_stub.h" | |
25 #include "content/common/gpu/gpu_memory_manager.h" | |
26 #include "gpu/command_buffer/service/valuebuffer_manager.h" | |
27 #include "gpu/ipc/common/gpu_stream_constants.h" | |
28 #include "ipc/ipc_sync_channel.h" | |
29 #include "ipc/message_router.h" | |
30 #include "ui/gfx/geometry/size.h" | |
31 #include "ui/gfx/native_widget_types.h" | |
32 #include "ui/gl/gl_share_group.h" | |
33 #include "ui/gl/gpu_preference.h" | |
34 | |
35 struct GPUCreateCommandBufferConfig; | |
36 | |
37 namespace base { | |
38 class WaitableEvent; | |
39 } | |
40 | |
41 namespace gpu { | |
42 class PreemptionFlag; | |
43 class SyncPointOrderData; | |
44 class SyncPointManager; | |
45 union ValueState; | |
46 class ValueStateMap; | |
47 namespace gles2 { | |
48 class SubscriptionRefSet; | |
49 } | |
50 } | |
51 | |
52 namespace IPC { | |
53 class MessageFilter; | |
54 } | |
55 | |
56 namespace content { | |
57 class GpuChannelManager; | |
58 class GpuChannelMessageFilter; | |
59 class GpuChannelMessageQueue; | |
60 class GpuWatchdog; | |
61 | |
62 // Encapsulates an IPC channel between the GPU process and one renderer | |
63 // process. On the renderer side there's a corresponding GpuChannelHost. | |
64 class CONTENT_EXPORT GpuChannel | |
65 : public IPC::Listener, | |
66 public IPC::Sender, | |
67 public gpu::gles2::SubscriptionRefSet::Observer { | |
68 public: | |
69 // Takes ownership of the renderer process handle. | |
70 GpuChannel(GpuChannelManager* gpu_channel_manager, | |
71 gpu::SyncPointManager* sync_point_manager, | |
72 GpuWatchdog* watchdog, | |
73 gfx::GLShareGroup* share_group, | |
74 gpu::gles2::MailboxManager* mailbox_manager, | |
75 gpu::PreemptionFlag* preempting_flag, | |
76 gpu::PreemptionFlag* preempted_flag, | |
77 base::SingleThreadTaskRunner* task_runner, | |
78 base::SingleThreadTaskRunner* io_task_runner, | |
79 int32_t client_id, | |
80 uint64_t client_tracing_id, | |
81 bool allow_view_command_buffers, | |
82 bool allow_real_time_streams); | |
83 ~GpuChannel() override; | |
84 | |
85 // Initializes the IPC channel. Caller takes ownership of the client FD in | |
86 // the returned handle and is responsible for closing it. | |
87 virtual IPC::ChannelHandle Init(base::WaitableEvent* shutdown_event); | |
88 | |
89 void SetUnhandledMessageListener(IPC::Listener* listener); | |
90 | |
91 // Get the GpuChannelManager that owns this channel. | |
92 GpuChannelManager* gpu_channel_manager() const { | |
93 return gpu_channel_manager_; | |
94 } | |
95 | |
96 const std::string& channel_id() const { return channel_id_; } | |
97 | |
98 virtual base::ProcessId GetClientPID() const; | |
99 | |
100 int client_id() const { return client_id_; } | |
101 | |
102 uint64_t client_tracing_id() const { return client_tracing_id_; } | |
103 | |
104 base::WeakPtr<GpuChannel> AsWeakPtr(); | |
105 | |
106 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() const { | |
107 return io_task_runner_; | |
108 } | |
109 | |
110 // IPC::Listener implementation: | |
111 bool OnMessageReceived(const IPC::Message& msg) override; | |
112 void OnChannelError() override; | |
113 | |
114 // IPC::Sender implementation: | |
115 bool Send(IPC::Message* msg) override; | |
116 | |
117 // SubscriptionRefSet::Observer implementation | |
118 void OnAddSubscription(unsigned int target) override; | |
119 void OnRemoveSubscription(unsigned int target) override; | |
120 | |
121 void OnStreamRescheduled(int32_t stream_id, bool scheduled); | |
122 | |
123 gfx::GLShareGroup* share_group() const { return share_group_.get(); } | |
124 | |
125 GpuCommandBufferStub* LookupCommandBuffer(int32_t route_id); | |
126 | |
127 void LoseAllContexts(); | |
128 void MarkAllContextsLost(); | |
129 | |
130 // Called to add a listener for a particular message routing ID. | |
131 // Returns true if succeeded. | |
132 bool AddRoute(int32_t route_id, int32_t stream_id, IPC::Listener* listener); | |
133 | |
134 // Called to remove a listener for a particular message routing ID. | |
135 void RemoveRoute(int32_t route_id); | |
136 | |
137 void CacheShader(const std::string& key, const std::string& shader); | |
138 | |
139 void AddFilter(IPC::MessageFilter* filter); | |
140 void RemoveFilter(IPC::MessageFilter* filter); | |
141 | |
142 uint64_t GetMemoryUsage(); | |
143 | |
144 scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( | |
145 const gfx::GpuMemoryBufferHandle& handle, | |
146 const gfx::Size& size, | |
147 gfx::BufferFormat format, | |
148 uint32_t internalformat); | |
149 | |
150 void HandleUpdateValueState(unsigned int target, | |
151 const gpu::ValueState& state); | |
152 | |
153 GpuChannelMessageFilter* filter() const { return filter_.get(); } | |
154 | |
155 // Visible for testing. | |
156 const gpu::ValueStateMap* pending_valuebuffer_state() const { | |
157 return pending_valuebuffer_state_.get(); | |
158 } | |
159 | |
160 // Returns the global order number for the last processed IPC message. | |
161 uint32_t GetProcessedOrderNum() const; | |
162 | |
163 // Returns the global order number for the last unprocessed IPC message. | |
164 uint32_t GetUnprocessedOrderNum() const; | |
165 | |
166 // Returns the shared sync point global order data for the stream. | |
167 scoped_refptr<gpu::SyncPointOrderData> GetSyncPointOrderData( | |
168 int32_t stream_id); | |
169 | |
170 void PostHandleOutOfOrderMessage(const IPC::Message& message); | |
171 void PostHandleMessage(const scoped_refptr<GpuChannelMessageQueue>& queue); | |
172 | |
173 // Synchronously handle the message to make testing convenient. | |
174 void HandleMessageForTesting(const IPC::Message& msg); | |
175 | |
176 #if defined(OS_ANDROID) | |
177 const GpuCommandBufferStub* GetOneStub() const; | |
178 #endif | |
179 | |
180 protected: | |
181 // The message filter on the io thread. | |
182 scoped_refptr<GpuChannelMessageFilter> filter_; | |
183 | |
184 // Map of routing id to command buffer stub. | |
185 base::ScopedPtrHashMap<int32_t, scoped_ptr<GpuCommandBufferStub>> stubs_; | |
186 | |
187 private: | |
188 bool OnControlMessageReceived(const IPC::Message& msg); | |
189 | |
190 void HandleMessage(const scoped_refptr<GpuChannelMessageQueue>& queue); | |
191 | |
192 // Some messages such as WaitForGetOffsetInRange and WaitForTokenInRange are | |
193 // processed as soon as possible because the client is blocked until they | |
194 // are completed. | |
195 void HandleOutOfOrderMessage(const IPC::Message& msg); | |
196 | |
197 void HandleMessageHelper(const IPC::Message& msg); | |
198 | |
199 scoped_refptr<GpuChannelMessageQueue> CreateStream( | |
200 int32_t stream_id, | |
201 gpu::GpuStreamPriority stream_priority); | |
202 | |
203 scoped_refptr<GpuChannelMessageQueue> LookupStream(int32_t stream_id); | |
204 | |
205 void DestroyStreamIfNecessary( | |
206 const scoped_refptr<GpuChannelMessageQueue>& queue); | |
207 | |
208 void AddRouteToStream(int32_t route_id, int32_t stream_id); | |
209 void RemoveRouteFromStream(int32_t route_id); | |
210 | |
211 // Message handlers for control messages. | |
212 void OnCreateCommandBuffer(gpu::SurfaceHandle surface_handle, | |
213 const gfx::Size& size, | |
214 const GPUCreateCommandBufferConfig& init_params, | |
215 int32_t route_id, | |
216 bool* succeeded); | |
217 void OnDestroyCommandBuffer(int32_t route_id); | |
218 void OnGetDriverBugWorkArounds( | |
219 std::vector<std::string>* gpu_driver_bug_workarounds); | |
220 | |
221 // The lifetime of objects of this class is managed by a GpuChannelManager. | |
222 // The GpuChannelManager destroy all the GpuChannels that they own when they | |
223 // are destroyed. So a raw pointer is safe. | |
224 GpuChannelManager* const gpu_channel_manager_; | |
225 | |
226 // Sync point manager. Outlives the channel and is guaranteed to outlive the | |
227 // message loop. | |
228 gpu::SyncPointManager* const sync_point_manager_; | |
229 | |
230 scoped_ptr<IPC::SyncChannel> channel_; | |
231 | |
232 IPC::Listener* unhandled_message_listener_; | |
233 | |
234 // Uniquely identifies the channel within this GPU process. | |
235 std::string channel_id_; | |
236 | |
237 // Used to implement message routing functionality to CommandBuffer objects | |
238 IPC::MessageRouter router_; | |
239 | |
240 // Whether the processing of IPCs on this channel is stalled and we should | |
241 // preempt other GpuChannels. | |
242 scoped_refptr<gpu::PreemptionFlag> preempting_flag_; | |
243 | |
244 // If non-NULL, all stubs on this channel should stop processing GL | |
245 // commands (via their CommandExecutor) when preempted_flag_->IsSet() | |
246 scoped_refptr<gpu::PreemptionFlag> preempted_flag_; | |
247 | |
248 // The id of the client who is on the other side of the channel. | |
249 const int32_t client_id_; | |
250 | |
251 // The tracing ID used for memory allocations associated with this client. | |
252 const uint64_t client_tracing_id_; | |
253 | |
254 // The task runners for the main thread and the io thread. | |
255 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
256 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; | |
257 | |
258 // The share group that all contexts associated with a particular renderer | |
259 // process use. | |
260 scoped_refptr<gfx::GLShareGroup> share_group_; | |
261 | |
262 scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_; | |
263 | |
264 scoped_refptr<gpu::gles2::SubscriptionRefSet> subscription_ref_set_; | |
265 | |
266 scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state_; | |
267 | |
268 gpu::gles2::DisallowedFeatures disallowed_features_; | |
269 GpuWatchdog* const watchdog_; | |
270 | |
271 // Map of stream id to appropriate message queue. | |
272 base::hash_map<int32_t, scoped_refptr<GpuChannelMessageQueue>> streams_; | |
273 | |
274 // Multimap of stream id to route ids. | |
275 base::hash_map<int32_t, int> streams_to_num_routes_; | |
276 | |
277 // Map of route id to stream id; | |
278 base::hash_map<int32_t, int32_t> routes_to_streams_; | |
279 | |
280 // Can view command buffers be created on this channel. | |
281 const bool allow_view_command_buffers_; | |
282 | |
283 // Can real time streams be created on this channel. | |
284 const bool allow_real_time_streams_; | |
285 | |
286 // Member variables should appear before the WeakPtrFactory, to ensure | |
287 // that any WeakPtrs to Controller are invalidated before its members | |
288 // variable's destructors are executed, rendering them invalid. | |
289 base::WeakPtrFactory<GpuChannel> weak_factory_; | |
290 | |
291 DISALLOW_COPY_AND_ASSIGN(GpuChannel); | |
292 }; | |
293 | |
294 // This filter does three things: | |
295 // - it counts and timestamps each message forwarded to the channel | |
296 // so that we can preempt other channels if a message takes too long to | |
297 // process. To guarantee fairness, we must wait a minimum amount of time | |
298 // before preempting and we limit the amount of time that we can preempt in | |
299 // one shot (see constants above). | |
300 // - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO | |
301 // thread, generating the sync point ID and responding immediately, and then | |
302 // posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message | |
303 // into the channel's queue. | |
304 // - it generates mailbox names for clients of the GPU process on the IO thread. | |
305 class GpuChannelMessageFilter : public IPC::MessageFilter { | |
306 public: | |
307 GpuChannelMessageFilter(); | |
308 | |
309 // IPC::MessageFilter implementation. | |
310 void OnFilterAdded(IPC::Sender* sender) override; | |
311 void OnFilterRemoved() override; | |
312 void OnChannelConnected(int32_t peer_pid) override; | |
313 void OnChannelError() override; | |
314 void OnChannelClosing() override; | |
315 bool OnMessageReceived(const IPC::Message& message) override; | |
316 | |
317 void AddChannelFilter(scoped_refptr<IPC::MessageFilter> filter); | |
318 void RemoveChannelFilter(scoped_refptr<IPC::MessageFilter> filter); | |
319 | |
320 void AddRoute(int32_t route_id, | |
321 const scoped_refptr<GpuChannelMessageQueue>& queue); | |
322 void RemoveRoute(int32_t route_id); | |
323 | |
324 bool Send(IPC::Message* message); | |
325 | |
326 protected: | |
327 ~GpuChannelMessageFilter() override; | |
328 | |
329 private: | |
330 scoped_refptr<GpuChannelMessageQueue> LookupStreamByRoute(int32_t route_id); | |
331 | |
332 bool MessageErrorHandler(const IPC::Message& message, const char* error_msg); | |
333 | |
334 // Map of route id to message queue. | |
335 base::hash_map<int32_t, scoped_refptr<GpuChannelMessageQueue>> routes_; | |
336 base::Lock routes_lock_; // Protects |routes_|. | |
337 | |
338 IPC::Sender* sender_; | |
339 base::ProcessId peer_pid_; | |
340 std::vector<scoped_refptr<IPC::MessageFilter>> channel_filters_; | |
341 | |
342 DISALLOW_COPY_AND_ASSIGN(GpuChannelMessageFilter); | |
343 }; | |
344 | |
345 struct GpuChannelMessage { | |
346 IPC::Message message; | |
347 uint32_t order_number; | |
348 base::TimeTicks time_received; | |
349 | |
350 GpuChannelMessage(const IPC::Message& msg, | |
351 uint32_t order_num, | |
352 base::TimeTicks ts) | |
353 : message(msg), order_number(order_num), time_received(ts) {} | |
354 | |
355 private: | |
356 DISALLOW_COPY_AND_ASSIGN(GpuChannelMessage); | |
357 }; | |
358 | |
359 class GpuChannelMessageQueue | |
360 : public base::RefCountedThreadSafe<GpuChannelMessageQueue> { | |
361 public: | |
362 static scoped_refptr<GpuChannelMessageQueue> Create( | |
363 int32_t stream_id, | |
364 gpu::GpuStreamPriority stream_priority, | |
365 GpuChannel* channel, | |
366 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, | |
367 const scoped_refptr<gpu::PreemptionFlag>& preempting_flag, | |
368 const scoped_refptr<gpu::PreemptionFlag>& preempted_flag, | |
369 gpu::SyncPointManager* sync_point_manager); | |
370 | |
371 void Disable(); | |
372 void DisableIO(); | |
373 | |
374 int32_t stream_id() const { return stream_id_; } | |
375 gpu::GpuStreamPriority stream_priority() const { return stream_priority_; } | |
376 | |
377 bool IsScheduled() const; | |
378 void OnRescheduled(bool scheduled); | |
379 | |
380 bool HasQueuedMessages() const; | |
381 | |
382 base::TimeTicks GetNextMessageTimeTick() const; | |
383 | |
384 scoped_refptr<gpu::SyncPointOrderData> GetSyncPointOrderData(); | |
385 | |
386 // Returns the global order number for the last unprocessed IPC message. | |
387 uint32_t GetUnprocessedOrderNum() const; | |
388 | |
389 // Returns the global order number for the last unprocessed IPC message. | |
390 uint32_t GetProcessedOrderNum() const; | |
391 | |
392 // Should be called before a message begins to be processed. Returns false if | |
393 // there are no messages to process. | |
394 const GpuChannelMessage* BeginMessageProcessing(); | |
395 // Should be called if a message began processing but did not finish. | |
396 void PauseMessageProcessing(); | |
397 // Should be called if a message is completely processed. Returns true if | |
398 // there are more messages to process. | |
399 void FinishMessageProcessing(); | |
400 | |
401 bool PushBackMessage(const IPC::Message& message); | |
402 | |
403 private: | |
404 enum PreemptionState { | |
405 // Either there's no other channel to preempt, there are no messages | |
406 // pending processing, or we just finished preempting and have to wait | |
407 // before preempting again. | |
408 IDLE, | |
409 // We are waiting kPreemptWaitTimeMs before checking if we should preempt. | |
410 WAITING, | |
411 // We can preempt whenever any IPC processing takes more than | |
412 // kPreemptWaitTimeMs. | |
413 CHECKING, | |
414 // We are currently preempting (i.e. no stub is descheduled). | |
415 PREEMPTING, | |
416 // We would like to preempt, but some stub is descheduled. | |
417 WOULD_PREEMPT_DESCHEDULED, | |
418 }; | |
419 | |
420 friend class base::RefCountedThreadSafe<GpuChannelMessageQueue>; | |
421 | |
422 GpuChannelMessageQueue( | |
423 int32_t stream_id, | |
424 gpu::GpuStreamPriority stream_priority, | |
425 GpuChannel* channel, | |
426 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, | |
427 const scoped_refptr<gpu::PreemptionFlag>& preempting_flag, | |
428 const scoped_refptr<gpu::PreemptionFlag>& preempted_flag, | |
429 gpu::SyncPointManager* sync_point_manager); | |
430 ~GpuChannelMessageQueue(); | |
431 | |
432 void UpdatePreemptionState(); | |
433 void UpdatePreemptionStateHelper(); | |
434 | |
435 void UpdateStateIdle(); | |
436 void UpdateStateWaiting(); | |
437 void UpdateStateChecking(); | |
438 void UpdateStatePreempting(); | |
439 void UpdateStateWouldPreemptDescheduled(); | |
440 | |
441 void TransitionToIdle(); | |
442 void TransitionToWaiting(); | |
443 void TransitionToChecking(); | |
444 void TransitionToPreempting(); | |
445 void TransitionToWouldPreemptDescheduled(); | |
446 | |
447 bool ShouldTransitionToIdle() const; | |
448 | |
449 const int32_t stream_id_; | |
450 const gpu::GpuStreamPriority stream_priority_; | |
451 | |
452 // These can be accessed from both IO and main threads and are protected by | |
453 // |channel_lock_|. | |
454 bool enabled_; | |
455 bool scheduled_; | |
456 GpuChannel* const channel_; | |
457 std::deque<scoped_ptr<GpuChannelMessage>> channel_messages_; | |
458 mutable base::Lock channel_lock_; | |
459 | |
460 // The following are accessed on the IO thread only. | |
461 // No lock is necessary for preemption state because it's only accessed on the | |
462 // IO thread. | |
463 PreemptionState preemption_state_; | |
464 // Maximum amount of time that we can spend in PREEMPTING. | |
465 // It is reset when we transition to IDLE. | |
466 base::TimeDelta max_preemption_time_; | |
467 // This timer is used and runs tasks on the IO thread. | |
468 scoped_ptr<base::OneShotTimer> timer_; | |
469 base::ThreadChecker io_thread_checker_; | |
470 | |
471 // Keeps track of sync point related state such as message order numbers. | |
472 scoped_refptr<gpu::SyncPointOrderData> sync_point_order_data_; | |
473 | |
474 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; | |
475 scoped_refptr<gpu::PreemptionFlag> preempting_flag_; | |
476 scoped_refptr<gpu::PreemptionFlag> preempted_flag_; | |
477 gpu::SyncPointManager* const sync_point_manager_; | |
478 | |
479 DISALLOW_COPY_AND_ASSIGN(GpuChannelMessageQueue); | |
480 }; | |
481 | |
482 } // namespace content | |
483 | |
484 #endif // CONTENT_COMMON_GPU_GPU_CHANNEL_H_ | |
OLD | NEW |