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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
10 #include "base/threading/thread_restrictions.h" | 10 #include "base/threading/thread_restrictions.h" |
11 #include "content/common/gpu/client/command_buffer_proxy_impl.h" | 11 #include "content/common/gpu/client/command_buffer_proxy_impl.h" |
12 #include "content/common/gpu/gpu_messages.h" | 12 #include "content/common/gpu/gpu_messages.h" |
13 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
14 #include "ipc/ipc_sync_message_filter.h" | 14 #include "ipc/ipc_sync_message_filter.h" |
15 | 15 |
16 using base::AutoLock; | 16 using base::AutoLock; |
17 using base::MessageLoopProxy; | 17 using base::MessageLoopProxy; |
18 | 18 |
19 GpuListenerInfo::GpuListenerInfo() { | 19 GpuListenerInfo::GpuListenerInfo() {} |
20 } | |
21 | 20 |
22 GpuListenerInfo::~GpuListenerInfo() { | 21 GpuListenerInfo::~GpuListenerInfo() {} |
23 } | |
24 | |
25 GpuChannelHost::MessageFilter::MessageFilter(GpuChannelHost* parent) | |
26 : parent_(parent) { | |
27 } | |
28 | |
29 GpuChannelHost::MessageFilter::~MessageFilter() { | |
30 | |
31 } | |
32 | |
33 void GpuChannelHost::MessageFilter::AddRoute( | |
34 int route_id, | |
35 base::WeakPtr<IPC::Channel::Listener> listener, | |
36 scoped_refptr<MessageLoopProxy> loop) { | |
37 DCHECK(parent_->factory_->IsIOThread()); | |
38 DCHECK(listeners_.find(route_id) == listeners_.end()); | |
39 GpuListenerInfo info; | |
40 info.listener = listener; | |
41 info.loop = loop; | |
42 listeners_[route_id] = info; | |
43 } | |
44 | |
45 void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) { | |
46 DCHECK(parent_->factory_->IsIOThread()); | |
47 ListenerMap::iterator it = listeners_.find(route_id); | |
48 if (it != listeners_.end()) | |
49 listeners_.erase(it); | |
50 } | |
51 | |
52 bool GpuChannelHost::MessageFilter::OnMessageReceived( | |
53 const IPC::Message& message) { | |
54 DCHECK(parent_->factory_->IsIOThread()); | |
55 // Never handle sync message replies or we will deadlock here. | |
56 if (message.is_reply()) | |
57 return false; | |
58 | |
59 DCHECK(message.routing_id() != MSG_ROUTING_CONTROL); | |
60 | |
61 ListenerMap::iterator it = listeners_.find(message.routing_id()); | |
62 | |
63 if (it != listeners_.end()) { | |
64 const GpuListenerInfo& info = it->second; | |
65 info.loop->PostTask( | |
66 FROM_HERE, | |
67 base::Bind( | |
68 base::IgnoreResult(&IPC::Channel::Listener::OnMessageReceived), | |
69 info.listener, | |
70 message)); | |
71 } | |
72 | |
73 return true; | |
74 } | |
75 | |
76 void GpuChannelHost::MessageFilter::OnChannelError() { | |
77 DCHECK(parent_->factory_->IsIOThread()); | |
78 // Inform all the proxies that an error has occurred. This will be reported | |
79 // via OpenGL as a lost context. | |
80 for (ListenerMap::iterator it = listeners_.begin(); | |
81 it != listeners_.end(); | |
82 it++) { | |
83 const GpuListenerInfo& info = it->second; | |
84 info.loop->PostTask( | |
85 FROM_HERE, | |
86 base::Bind(&IPC::Channel::Listener::OnChannelError, info.listener)); | |
87 } | |
88 | |
89 listeners_.clear(); | |
90 | |
91 MessageLoop* main_loop = parent_->factory_->GetMainLoop(); | |
92 main_loop->PostTask(FROM_HERE, | |
93 base::Bind(&GpuChannelHost::OnChannelError, parent_)); | |
94 } | |
95 | 22 |
96 GpuChannelHost::GpuChannelHost( | 23 GpuChannelHost::GpuChannelHost( |
97 GpuChannelHostFactory* factory, int gpu_host_id, int client_id) | 24 GpuChannelHostFactory* factory, int gpu_host_id, int client_id) |
98 : factory_(factory), | 25 : factory_(factory), |
99 client_id_(client_id), | 26 client_id_(client_id), |
100 gpu_host_id_(gpu_host_id), | 27 gpu_host_id_(gpu_host_id), |
101 state_(kUnconnected) { | 28 state_(kUnconnected) { |
102 } | 29 } |
103 | 30 |
104 GpuChannelHost::~GpuChannelHost() { | |
105 } | |
106 | |
107 void GpuChannelHost::Connect( | 31 void GpuChannelHost::Connect( |
108 const IPC::ChannelHandle& channel_handle) { | 32 const IPC::ChannelHandle& channel_handle) { |
109 DCHECK(factory_->IsMainThread()); | 33 DCHECK(factory_->IsMainThread()); |
110 // Open a channel to the GPU process. We pass NULL as the main listener here | 34 // Open a channel to the GPU process. We pass NULL as the main listener here |
111 // since we need to filter everything to route it to the right thread. | 35 // since we need to filter everything to route it to the right thread. |
112 scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); | 36 scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); |
113 channel_.reset(new IPC::SyncChannel( | 37 channel_.reset(new IPC::SyncChannel( |
114 channel_handle, IPC::Channel::MODE_CLIENT, NULL, | 38 channel_handle, IPC::Channel::MODE_CLIENT, NULL, |
115 io_loop, true, | 39 io_loop, true, |
116 factory_->GetShutDownEvent())); | 40 factory_->GetShutDownEvent())); |
(...skipping 12 matching lines...) Expand all Loading... |
129 // It is safe to send IPC messages before the channel completes the connection | 53 // It is safe to send IPC messages before the channel completes the connection |
130 // and receives the hello message from the GPU process. The messages get | 54 // and receives the hello message from the GPU process. The messages get |
131 // cached. | 55 // cached. |
132 state_ = kConnected; | 56 state_ = kConnected; |
133 } | 57 } |
134 | 58 |
135 void GpuChannelHost::set_gpu_info(const content::GPUInfo& gpu_info) { | 59 void GpuChannelHost::set_gpu_info(const content::GPUInfo& gpu_info) { |
136 gpu_info_ = gpu_info; | 60 gpu_info_ = gpu_info; |
137 } | 61 } |
138 | 62 |
| 63 void GpuChannelHost::SetStateLost() { |
| 64 state_ = kLost; |
| 65 } |
| 66 |
139 const content::GPUInfo& GpuChannelHost::gpu_info() const { | 67 const content::GPUInfo& GpuChannelHost::gpu_info() const { |
140 return gpu_info_; | 68 return gpu_info_; |
141 } | 69 } |
142 | 70 |
143 void GpuChannelHost::SetStateLost() { | |
144 state_ = kLost; | |
145 } | |
146 | |
147 void GpuChannelHost::OnChannelError() { | 71 void GpuChannelHost::OnChannelError() { |
148 state_ = kLost; | 72 state_ = kLost; |
149 | 73 |
150 // Channel is invalid and will be reinitialized if this host is requested | 74 // Channel is invalid and will be reinitialized if this host is requested |
151 // again. | 75 // again. |
152 channel_.reset(); | 76 channel_.reset(); |
153 } | 77 } |
154 | 78 |
155 bool GpuChannelHost::Send(IPC::Message* message) { | 79 bool GpuChannelHost::Send(IPC::Message* message) { |
156 // The GPU process never sends synchronous IPCs so clear the unblock flag to | 80 // The GPU process never sends synchronous IPCs so clear the unblock flag to |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 CommandBufferProxyImpl* command_buffer = | 132 CommandBufferProxyImpl* command_buffer = |
209 new CommandBufferProxyImpl(this, route_id); | 133 new CommandBufferProxyImpl(this, route_id); |
210 AddRoute(route_id, command_buffer->AsWeakPtr()); | 134 AddRoute(route_id, command_buffer->AsWeakPtr()); |
211 proxies_[route_id] = command_buffer; | 135 proxies_[route_id] = command_buffer; |
212 return command_buffer; | 136 return command_buffer; |
213 #else | 137 #else |
214 return NULL; | 138 return NULL; |
215 #endif | 139 #endif |
216 } | 140 } |
217 | 141 |
218 GpuVideoDecodeAcceleratorHost* GpuChannelHost::CreateVideoDecoder( | |
219 int command_buffer_route_id, | |
220 media::VideoCodecProfile profile, | |
221 media::VideoDecodeAccelerator::Client* client) { | |
222 AutoLock lock(context_lock_); | |
223 ProxyMap::iterator it = proxies_.find(command_buffer_route_id); | |
224 DCHECK(it != proxies_.end()); | |
225 CommandBufferProxyImpl* proxy = it->second; | |
226 return proxy->CreateVideoDecoder(profile, client); | |
227 } | |
228 | |
229 CommandBufferProxy* GpuChannelHost::CreateOffscreenCommandBuffer( | 142 CommandBufferProxy* GpuChannelHost::CreateOffscreenCommandBuffer( |
230 const gfx::Size& size, | 143 const gfx::Size& size, |
231 CommandBufferProxy* share_group, | 144 CommandBufferProxy* share_group, |
232 const std::string& allowed_extensions, | 145 const std::string& allowed_extensions, |
233 const std::vector<int32>& attribs, | 146 const std::vector<int32>& attribs, |
234 const GURL& active_url, | 147 const GURL& active_url, |
235 gfx::GpuPreference gpu_preference) { | 148 gfx::GpuPreference gpu_preference) { |
236 #if defined(ENABLE_GPU) | 149 #if defined(ENABLE_GPU) |
237 AutoLock lock(context_lock_); | 150 AutoLock lock(context_lock_); |
238 // An error occurred. Need to get the host again to reinitialize it. | 151 // An error occurred. Need to get the host again to reinitialize it. |
(...skipping 20 matching lines...) Expand all Loading... |
259 CommandBufferProxyImpl* command_buffer = | 172 CommandBufferProxyImpl* command_buffer = |
260 new CommandBufferProxyImpl(this, route_id); | 173 new CommandBufferProxyImpl(this, route_id); |
261 AddRoute(route_id, command_buffer->AsWeakPtr()); | 174 AddRoute(route_id, command_buffer->AsWeakPtr()); |
262 proxies_[route_id] = command_buffer; | 175 proxies_[route_id] = command_buffer; |
263 return command_buffer; | 176 return command_buffer; |
264 #else | 177 #else |
265 return NULL; | 178 return NULL; |
266 #endif | 179 #endif |
267 } | 180 } |
268 | 181 |
| 182 GpuVideoDecodeAcceleratorHost* GpuChannelHost::CreateVideoDecoder( |
| 183 int command_buffer_route_id, |
| 184 media::VideoCodecProfile profile, |
| 185 media::VideoDecodeAccelerator::Client* client) { |
| 186 AutoLock lock(context_lock_); |
| 187 ProxyMap::iterator it = proxies_.find(command_buffer_route_id); |
| 188 DCHECK(it != proxies_.end()); |
| 189 CommandBufferProxyImpl* proxy = it->second; |
| 190 return proxy->CreateVideoDecoder(profile, client); |
| 191 } |
| 192 |
269 void GpuChannelHost::DestroyCommandBuffer( | 193 void GpuChannelHost::DestroyCommandBuffer( |
270 CommandBufferProxy* command_buffer) { | 194 CommandBufferProxy* command_buffer) { |
271 #if defined(ENABLE_GPU) | 195 #if defined(ENABLE_GPU) |
272 AutoLock lock(context_lock_); | 196 AutoLock lock(context_lock_); |
273 int route_id = command_buffer->GetRouteID(); | 197 int route_id = command_buffer->GetRouteID(); |
274 Send(new GpuChannelMsg_DestroyCommandBuffer(route_id)); | 198 Send(new GpuChannelMsg_DestroyCommandBuffer(route_id)); |
275 // Check the proxy has not already been removed after a channel error. | 199 // Check the proxy has not already been removed after a channel error. |
276 if (proxies_.find(route_id) != proxies_.end()) | 200 if (proxies_.find(route_id) != proxies_.end()) |
277 proxies_.erase(route_id); | 201 proxies_.erase(route_id); |
278 RemoveRoute(route_id); | 202 RemoveRoute(route_id); |
(...skipping 27 matching lines...) Expand all Loading... |
306 &result))) { | 230 &result))) { |
307 return false; | 231 return false; |
308 } | 232 } |
309 return result; | 233 return result; |
310 } | 234 } |
311 | 235 |
312 void GpuChannelHost::ForciblyCloseChannel() { | 236 void GpuChannelHost::ForciblyCloseChannel() { |
313 Send(new GpuChannelMsg_CloseChannel()); | 237 Send(new GpuChannelMsg_CloseChannel()); |
314 SetStateLost(); | 238 SetStateLost(); |
315 } | 239 } |
| 240 |
| 241 GpuChannelHost::~GpuChannelHost() {} |
| 242 |
| 243 |
| 244 GpuChannelHost::MessageFilter::MessageFilter(GpuChannelHost* parent) |
| 245 : parent_(parent) { |
| 246 } |
| 247 |
| 248 GpuChannelHost::MessageFilter::~MessageFilter() {} |
| 249 |
| 250 void GpuChannelHost::MessageFilter::AddRoute( |
| 251 int route_id, |
| 252 base::WeakPtr<IPC::Channel::Listener> listener, |
| 253 scoped_refptr<MessageLoopProxy> loop) { |
| 254 DCHECK(parent_->factory_->IsIOThread()); |
| 255 DCHECK(listeners_.find(route_id) == listeners_.end()); |
| 256 GpuListenerInfo info; |
| 257 info.listener = listener; |
| 258 info.loop = loop; |
| 259 listeners_[route_id] = info; |
| 260 } |
| 261 |
| 262 void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) { |
| 263 DCHECK(parent_->factory_->IsIOThread()); |
| 264 ListenerMap::iterator it = listeners_.find(route_id); |
| 265 if (it != listeners_.end()) |
| 266 listeners_.erase(it); |
| 267 } |
| 268 |
| 269 bool GpuChannelHost::MessageFilter::OnMessageReceived( |
| 270 const IPC::Message& message) { |
| 271 DCHECK(parent_->factory_->IsIOThread()); |
| 272 // Never handle sync message replies or we will deadlock here. |
| 273 if (message.is_reply()) |
| 274 return false; |
| 275 |
| 276 DCHECK(message.routing_id() != MSG_ROUTING_CONTROL); |
| 277 |
| 278 ListenerMap::iterator it = listeners_.find(message.routing_id()); |
| 279 |
| 280 if (it != listeners_.end()) { |
| 281 const GpuListenerInfo& info = it->second; |
| 282 info.loop->PostTask( |
| 283 FROM_HERE, |
| 284 base::Bind( |
| 285 base::IgnoreResult(&IPC::Channel::Listener::OnMessageReceived), |
| 286 info.listener, |
| 287 message)); |
| 288 } |
| 289 |
| 290 return true; |
| 291 } |
| 292 |
| 293 void GpuChannelHost::MessageFilter::OnChannelError() { |
| 294 DCHECK(parent_->factory_->IsIOThread()); |
| 295 // Inform all the proxies that an error has occurred. This will be reported |
| 296 // via OpenGL as a lost context. |
| 297 for (ListenerMap::iterator it = listeners_.begin(); |
| 298 it != listeners_.end(); |
| 299 it++) { |
| 300 const GpuListenerInfo& info = it->second; |
| 301 info.loop->PostTask( |
| 302 FROM_HERE, |
| 303 base::Bind(&IPC::Channel::Listener::OnChannelError, info.listener)); |
| 304 } |
| 305 |
| 306 listeners_.clear(); |
| 307 |
| 308 MessageLoop* main_loop = parent_->factory_->GetMainLoop(); |
| 309 main_loop->PostTask(FROM_HERE, |
| 310 base::Bind(&GpuChannelHost::OnChannelError, parent_)); |
| 311 } |
| 312 |
| 313 |
OLD | NEW |