OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/client/gpu_channel_host.h" | 5 #include "content/common/gpu/client/gpu_channel_host.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 : factory_(factory), | 61 : factory_(factory), |
62 gpu_info_(gpu_info), | 62 gpu_info_(gpu_info), |
63 gpu_memory_buffer_manager_(gpu_memory_buffer_manager) { | 63 gpu_memory_buffer_manager_(gpu_memory_buffer_manager) { |
64 next_transfer_buffer_id_.GetNext(); | 64 next_transfer_buffer_id_.GetNext(); |
65 next_image_id_.GetNext(); | 65 next_image_id_.GetNext(); |
66 next_route_id_.GetNext(); | 66 next_route_id_.GetNext(); |
67 } | 67 } |
68 | 68 |
69 void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle, | 69 void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle, |
70 base::WaitableEvent* shutdown_event) { | 70 base::WaitableEvent* shutdown_event) { |
| 71 DCHECK(factory_->IsMainThread()); |
71 // Open a channel to the GPU process. We pass NULL as the main listener here | 72 // Open a channel to the GPU process. We pass NULL as the main listener here |
72 // since we need to filter everything to route it to the right thread. | 73 // since we need to filter everything to route it to the right thread. |
73 scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); | 74 scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); |
74 channel_ = IPC::SyncChannel::Create(channel_handle, | 75 channel_ = IPC::SyncChannel::Create(channel_handle, |
75 IPC::Channel::MODE_CLIENT, | 76 IPC::Channel::MODE_CLIENT, |
76 NULL, | 77 NULL, |
77 io_loop.get(), | 78 io_loop.get(), |
78 true, | 79 true, |
79 shutdown_event); | 80 shutdown_event); |
80 | 81 |
(...skipping 18 matching lines...) Expand all Loading... |
99 | 100 |
100 // Currently we need to choose between two different mechanisms for sending. | 101 // Currently we need to choose between two different mechanisms for sending. |
101 // On the main thread we use the regular channel Send() method, on another | 102 // On the main thread we use the regular channel Send() method, on another |
102 // thread we use SyncMessageFilter. We also have to be careful interpreting | 103 // thread we use SyncMessageFilter. We also have to be careful interpreting |
103 // IsMainThread() since it might return false during shutdown, | 104 // IsMainThread() since it might return false during shutdown, |
104 // impl we are actually calling from the main thread (discard message then). | 105 // impl we are actually calling from the main thread (discard message then). |
105 // | 106 // |
106 // TODO: Can we just always use sync_filter_ since we setup the channel | 107 // TODO: Can we just always use sync_filter_ since we setup the channel |
107 // without a main listener? | 108 // without a main listener? |
108 if (factory_->IsMainThread()) { | 109 if (factory_->IsMainThread()) { |
| 110 // channel_ is only modified on the main thread, so we don't need to take a |
| 111 // lock here. |
| 112 if (!channel_) { |
| 113 DVLOG(1) << "GpuChannelHost::Send failed: Channel already destroyed"; |
| 114 return false; |
| 115 } |
109 // http://crbug.com/125264 | 116 // http://crbug.com/125264 |
110 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 117 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
111 bool result = channel_->Send(message.release()); | 118 bool result = channel_->Send(message.release()); |
112 if (!result) | 119 if (!result) |
113 DVLOG(1) << "GpuChannelHost::Send failed: Channel::Send failed"; | 120 DVLOG(1) << "GpuChannelHost::Send failed: Channel::Send failed"; |
114 return result; | 121 return result; |
115 } | 122 } |
116 | 123 |
117 bool result = sync_filter_->Send(message.release()); | 124 bool result = sync_filter_->Send(message.release()); |
118 return result; | 125 return result; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 | 273 |
267 AutoLock lock(context_lock_); | 274 AutoLock lock(context_lock_); |
268 proxies_.erase(route_id); | 275 proxies_.erase(route_id); |
269 if (flush_info_.flush_pending && flush_info_.route_id == route_id) | 276 if (flush_info_.flush_pending && flush_info_.route_id == route_id) |
270 flush_info_.flush_pending = false; | 277 flush_info_.flush_pending = false; |
271 | 278 |
272 delete command_buffer; | 279 delete command_buffer; |
273 } | 280 } |
274 | 281 |
275 void GpuChannelHost::DestroyChannel() { | 282 void GpuChannelHost::DestroyChannel() { |
276 // channel_ must be destroyed on the main thread. | 283 DCHECK(factory_->IsMainThread()); |
277 if (channel_.get() && !factory_->IsMainThread()) | 284 AutoLock lock(context_lock_); |
278 factory_->GetMainLoop()->DeleteSoon(FROM_HERE, channel_.release()); | |
279 channel_.reset(); | 285 channel_.reset(); |
280 } | 286 } |
281 | 287 |
282 void GpuChannelHost::AddRoute( | 288 void GpuChannelHost::AddRoute( |
283 int route_id, base::WeakPtr<IPC::Listener> listener) { | 289 int route_id, base::WeakPtr<IPC::Listener> listener) { |
284 DCHECK(MessageLoopProxy::current().get()); | 290 DCHECK(MessageLoopProxy::current().get()); |
285 | 291 |
286 scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); | 292 scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); |
287 io_loop->PostTask(FROM_HERE, | 293 io_loop->PostTask(FROM_HERE, |
288 base::Bind(&GpuChannelHost::MessageFilter::AddRoute, | 294 base::Bind(&GpuChannelHost::MessageFilter::AddRoute, |
289 channel_filter_.get(), route_id, listener, | 295 channel_filter_.get(), route_id, listener, |
290 MessageLoopProxy::current())); | 296 MessageLoopProxy::current())); |
291 } | 297 } |
292 | 298 |
293 void GpuChannelHost::RemoveRoute(int route_id) { | 299 void GpuChannelHost::RemoveRoute(int route_id) { |
294 scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); | 300 scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); |
295 io_loop->PostTask(FROM_HERE, | 301 io_loop->PostTask(FROM_HERE, |
296 base::Bind(&GpuChannelHost::MessageFilter::RemoveRoute, | 302 base::Bind(&GpuChannelHost::MessageFilter::RemoveRoute, |
297 channel_filter_.get(), route_id)); | 303 channel_filter_.get(), route_id)); |
298 } | 304 } |
299 | 305 |
300 base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess( | 306 base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess( |
301 base::SharedMemoryHandle source_handle) { | 307 base::SharedMemoryHandle source_handle) { |
302 if (IsLost()) | 308 if (IsLost()) |
303 return base::SharedMemory::NULLHandle(); | 309 return base::SharedMemory::NULLHandle(); |
304 | 310 |
305 #if defined(OS_WIN) | 311 #if defined(OS_WIN) |
306 // Windows needs to explicitly duplicate the handle out to another process. | 312 // Windows needs to explicitly duplicate the handle out to another process. |
307 base::SharedMemoryHandle target_handle; | 313 base::SharedMemoryHandle target_handle; |
| 314 base::ProcessId peer_pid; |
| 315 { |
| 316 AutoLock lock(context_lock_); |
| 317 if (!channel_) |
| 318 return base::SharedMemory::NULLHandle(); |
| 319 peer_pid = channel_->GetPeerPID(); |
| 320 } |
308 if (!BrokerDuplicateHandle(source_handle, | 321 if (!BrokerDuplicateHandle(source_handle, |
309 channel_->GetPeerPID(), | 322 peer_pid, |
310 &target_handle, | 323 &target_handle, |
311 FILE_GENERIC_READ | FILE_GENERIC_WRITE, | 324 FILE_GENERIC_READ | FILE_GENERIC_WRITE, |
312 0)) { | 325 0)) { |
313 return base::SharedMemory::NULLHandle(); | 326 return base::SharedMemory::NULLHandle(); |
314 } | 327 } |
315 | 328 |
316 return target_handle; | 329 return target_handle; |
317 #else | 330 #else |
318 int duped_handle = HANDLE_EINTR(dup(source_handle.fd)); | 331 int duped_handle = HANDLE_EINTR(dup(source_handle.fd)); |
319 if (duped_handle < 0) | 332 if (duped_handle < 0) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 | 364 |
352 int32 GpuChannelHost::ReserveImageId() { | 365 int32 GpuChannelHost::ReserveImageId() { |
353 return next_image_id_.GetNext(); | 366 return next_image_id_.GetNext(); |
354 } | 367 } |
355 | 368 |
356 int32 GpuChannelHost::GenerateRouteID() { | 369 int32 GpuChannelHost::GenerateRouteID() { |
357 return next_route_id_.GetNext(); | 370 return next_route_id_.GetNext(); |
358 } | 371 } |
359 | 372 |
360 GpuChannelHost::~GpuChannelHost() { | 373 GpuChannelHost::~GpuChannelHost() { |
361 DestroyChannel(); | 374 #if DCHECK_IS_ON() |
| 375 AutoLock lock(context_lock_); |
| 376 DCHECK(!channel_) |
| 377 << "GpuChannelHost::DestroyChannel must be called before destruction."; |
| 378 #endif |
362 } | 379 } |
363 | 380 |
364 GpuChannelHost::MessageFilter::MessageFilter() | 381 GpuChannelHost::MessageFilter::MessageFilter() |
365 : lost_(false) { | 382 : lost_(false) { |
366 } | 383 } |
367 | 384 |
368 GpuChannelHost::MessageFilter::~MessageFilter() {} | 385 GpuChannelHost::MessageFilter::~MessageFilter() {} |
369 | 386 |
370 void GpuChannelHost::MessageFilter::AddRoute( | 387 void GpuChannelHost::MessageFilter::AddRoute( |
371 int route_id, | 388 int route_id, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 | 443 |
427 listeners_.clear(); | 444 listeners_.clear(); |
428 } | 445 } |
429 | 446 |
430 bool GpuChannelHost::MessageFilter::IsLost() const { | 447 bool GpuChannelHost::MessageFilter::IsLost() const { |
431 AutoLock lock(lock_); | 448 AutoLock lock(lock_); |
432 return lost_; | 449 return lost_; |
433 } | 450 } |
434 | 451 |
435 } // namespace content | 452 } // namespace content |
OLD | NEW |