Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Side by Side Diff: content/renderer/gpu/gpu_channel_host.cc

Issue 7634019: Allow cmdbuffer creation from compositor thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: MessageLoop::current() -> MessageLoopProxy::current() Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/renderer/gpu/gpu_channel_host.h" 5 #include "content/renderer/gpu/gpu_channel_host.h"
6 6
7 #include "base/message_loop_proxy.h"
7 #include "content/common/child_process.h" 8 #include "content/common/child_process.h"
8 #include "content/common/gpu/gpu_messages.h" 9 #include "content/common/gpu/gpu_messages.h"
9 #include "content/renderer/gpu/command_buffer_proxy.h" 10 #include "content/renderer/gpu/command_buffer_proxy.h"
10 #include "content/renderer/gpu/gpu_surface_proxy.h" 11 #include "content/renderer/gpu/gpu_surface_proxy.h"
11 #include "content/renderer/gpu/transport_texture_service.h" 12 #include "content/renderer/gpu/transport_texture_service.h"
13 #include "content/renderer/render_process.h"
12 #include "content/renderer/render_thread.h" 14 #include "content/renderer/render_thread.h"
13 #include "googleurl/src/gurl.h" 15 #include "googleurl/src/gurl.h"
16 #include "ipc/ipc_sync_message_filter.h"
17
18 using base::AutoLock;
19 using base::MessageLoopProxy;
20
21 GpuChannelHost::MessageFilter::Listener::Listener()
22 : orphaned_(false) {
23
24 }
25
26 GpuChannelHost::MessageFilter::Listener::~Listener() {
27
28 }
29
30 GpuChannelHost::MessageFilter::ListenerInfo::ListenerInfo() : loop_(NULL) {
31
32 }
33
34 GpuChannelHost::MessageFilter::ListenerInfo::ListenerInfo(
35 MessageLoopProxy* loop, scoped_refptr<Listener> listener)
36 : loop_(loop),
37 listener_(listener) {
38 }
39
40 GpuChannelHost::MessageFilter::ListenerInfo::~ListenerInfo() {
41
42 }
43
44 GpuChannelHost::MessageFilter::MessageFilter(GpuChannelHost* parent)
45 : parent_(parent) {
46 DetachFromThread();
47 }
48
49 void GpuChannelHost::MessageFilter::AddRoute(
50 int route_id,
51 scoped_refptr<Listener> listener,
52 MessageLoopProxy* loop) {
53 DCHECK(CalledOnValidThread());
54 DCHECK(listeners_.find(route_id) == listeners_.end());
55 listeners_[route_id] = ListenerInfo(loop, listener);
56 }
57
58 void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) {
59 DCHECK(CalledOnValidThread());
60 ListenerMap::iterator it = listeners_.find(route_id);
61 if (it != listeners_.end())
62 listeners_.erase(it);
63 }
64
65 bool GpuChannelHost::MessageFilter::OnMessageReceived(
66 const IPC::Message& message) {
67 DCHECK(CalledOnValidThread());
68
69 // Never handle sync message replies or we will deadlock here.
70 if (message.is_reply())
71 return false;
72
73 DCHECK(message.routing_id() != MSG_ROUTING_CONTROL);
74
75 ListenerMap::iterator it = listeners_.find(message.routing_id());
76
77 if (it != listeners_.end()) {
78 const ListenerInfo& info = it->second;
79 info.loop_->PostTask(
80 FROM_HERE,
81 NewRunnableMethod(
82 info.listener_.get(),
83 &GpuChannelHost::MessageFilter::Listener::OnMessageReceived,
84 message));
85 }
86
87 return true;
88 }
89
90 void GpuChannelHost::MessageFilter::OnChannelError() {
91 DCHECK(CalledOnValidThread());
92
93 // Inform all the proxies that an error has occurred. This will be reported
94 // via OpenGL as a lost context.
95 for (ListenerMap::iterator it = listeners_.begin();
96 it != listeners_.end();
97 it++) {
98 const ListenerInfo& info = it->second;
99 info.loop_->PostTask(
100 FROM_HERE,
101 NewRunnableMethod(
102 info.listener_.get(),
103 &GpuChannelHost::MessageFilter::Listener::OnChannelError));
104 }
105
106 listeners_.clear();
107
108 ChildThread* main_thread = RenderProcess::current()->main_thread();
109 MessageLoop* main_loop = main_thread->message_loop();
110 main_loop->PostTask(FROM_HERE,
111 NewRunnableMethod(parent_,
112 &GpuChannelHost::OnChannelError));
113 }
14 114
15 GpuChannelHost::GpuChannelHost() 115 GpuChannelHost::GpuChannelHost()
16 : state_(kUnconnected), 116 : state_(kUnconnected),
17 transport_texture_service_(new TransportTextureService()) { 117 transport_texture_service_(new TransportTextureService()) {
18 } 118 }
19 119
20 GpuChannelHost::~GpuChannelHost() { 120 GpuChannelHost::~GpuChannelHost() {
21 } 121 }
22 122
23 void GpuChannelHost::Connect( 123 void GpuChannelHost::Connect(
24 const IPC::ChannelHandle& channel_handle, 124 const IPC::ChannelHandle& channel_handle,
25 base::ProcessHandle renderer_process_for_gpu) { 125 base::ProcessHandle renderer_process_for_gpu) {
26 // Open a channel to the GPU process. 126 DCHECK(RenderThread::current());
127 // Open a channel to the GPU process. We pass NULL as the main listener here
128 // since we need to filter everything to route it to the right thread.
27 channel_.reset(new IPC::SyncChannel( 129 channel_.reset(new IPC::SyncChannel(
28 channel_handle, IPC::Channel::MODE_CLIENT, this, 130 channel_handle, IPC::Channel::MODE_CLIENT, NULL,
29 ChildProcess::current()->io_message_loop_proxy(), true, 131 ChildProcess::current()->io_message_loop_proxy(), true,
30 ChildProcess::current()->GetShutDownEvent())); 132 ChildProcess::current()->GetShutDownEvent()));
31 133
134 sync_filter_.reset(new IPC::SyncMessageFilter(
135 ChildProcess::current()->GetShutDownEvent()));
136
137 channel_->AddFilter(sync_filter_.get());
138
139 channel_->AddFilter(transport_texture_service_.get());
140
141 channel_filter_ = new MessageFilter(this);
142
143 // Install the filter last, because we intercept all leftover
144 // messages.
145 channel_->AddFilter(channel_filter_.get());
146
32 // It is safe to send IPC messages before the channel completes the connection 147 // It is safe to send IPC messages before the channel completes the connection
33 // and receives the hello message from the GPU process. The messages get 148 // and receives the hello message from the GPU process. The messages get
34 // cached. 149 // cached.
35 state_ = kConnected; 150 state_ = kConnected;
36 151
37 // Notify the GPU process of our process handle. This gives it the ability 152 // Notify the GPU process of our process handle. This gives it the ability
38 // to map renderer handles into the GPU process. 153 // to map renderer handles into the GPU process.
39 Send(new GpuChannelMsg_Initialize(renderer_process_for_gpu)); 154 Send(new GpuChannelMsg_Initialize(renderer_process_for_gpu));
40 } 155 }
41 156
42 void GpuChannelHost::set_gpu_info(const GPUInfo& gpu_info) { 157 void GpuChannelHost::set_gpu_info(const GPUInfo& gpu_info) {
43 gpu_info_ = gpu_info; 158 gpu_info_ = gpu_info;
44 } 159 }
45 160
46 const GPUInfo& GpuChannelHost::gpu_info() const { 161 const GPUInfo& GpuChannelHost::gpu_info() const {
47 return gpu_info_; 162 return gpu_info_;
48 } 163 }
49 164
50 void GpuChannelHost::SetStateLost() { 165 void GpuChannelHost::SetStateLost() {
51 state_ = kLost; 166 state_ = kLost;
52 } 167 }
53 168
54 bool GpuChannelHost::OnMessageReceived(const IPC::Message& message) {
55 DCHECK(message.routing_id() != MSG_ROUTING_CONTROL);
56
57 return router_.RouteMessage(message);
58 }
59
60 void GpuChannelHost::OnChannelConnected(int32 peer_pid) {
61 channel_->AddFilter(transport_texture_service_.get());
62 }
63
64 void GpuChannelHost::OnChannelError() { 169 void GpuChannelHost::OnChannelError() {
65 state_ = kLost; 170 state_ = kLost;
66 171
67 // Channel is invalid and will be reinitialized if this host is requested 172 // Channel is invalid and will be reinitialized if this host is requested
68 // again. 173 // again.
69 channel_.reset(); 174 channel_.reset();
70
71 // Inform all the proxies that an error has occured. This will be reported via
72 // OpenGL as a lost context.
73 for (ProxyMap::iterator iter = proxies_.begin();
74 iter != proxies_.end(); iter++) {
75 router_.RemoveRoute(iter->first);
76 iter->second->OnChannelError();
77 }
78
79 // The proxies are reference counted so this will not result in their
80 // destruction if the client still holds a reference. The proxy will report
81 // a lost context, indicating to the client that it needs to be recreated.
82 proxies_.clear();
83 } 175 }
84 176
85 bool GpuChannelHost::Send(IPC::Message* message) { 177 bool GpuChannelHost::Send(IPC::Message* message) {
86 // The GPU process never sends synchronous IPCs so clear the unblock flag to 178 // The GPU process never sends synchronous IPCs so clear the unblock flag to
87 // preserve order. 179 // preserve order.
88 message->set_unblock(false); 180 message->set_unblock(false);
89 if (channel_.get()) 181
182 // Unfortunately a sync filter cannot be used on the main (listener) thread.
183 // TODO: Is that true even when we don't install a listener?
184 if (channel_.get() && RenderThread::current())
90 return channel_->Send(message); 185 return channel_->Send(message);
186 else
187 return sync_filter_->Send(message);
91 188
92 // Callee takes ownership of message, regardless of whether Send is 189 // Callee takes ownership of message, regardless of whether Send is
93 // successful. See IPC::Message::Sender. 190 // successful. See IPC::Message::Sender.
94 delete message; 191 delete message;
95 return false; 192 return false;
96 } 193 }
97 194
98 CommandBufferProxy* GpuChannelHost::CreateViewCommandBuffer( 195 scoped_refptr<CommandBufferProxy> GpuChannelHost::CreateViewCommandBuffer(
99 int render_view_id, 196 int render_view_id,
100 CommandBufferProxy* share_group, 197 CommandBufferProxy* share_group,
101 const std::string& allowed_extensions, 198 const std::string& allowed_extensions,
102 const std::vector<int32>& attribs, 199 const std::vector<int32>& attribs,
103 const GURL& active_url) { 200 const GURL& active_url) {
104 #if defined(ENABLE_GPU) 201 #if defined(ENABLE_GPU)
202 AutoLock lock(context_lock_);
105 // An error occurred. Need to get the host again to reinitialize it. 203 // An error occurred. Need to get the host again to reinitialize it.
106 if (!channel_.get()) 204 if (!channel_.get())
107 return NULL; 205 return NULL;
108 206
109 GPUCreateCommandBufferConfig init_params; 207 GPUCreateCommandBufferConfig init_params;
110 init_params.share_group_id = 208 init_params.share_group_id =
111 share_group ? share_group->route_id() : MSG_ROUTING_NONE; 209 share_group ? share_group->route_id() : MSG_ROUTING_NONE;
112 init_params.allowed_extensions = allowed_extensions; 210 init_params.allowed_extensions = allowed_extensions;
113 init_params.attribs = attribs; 211 init_params.attribs = attribs;
114 init_params.active_url = active_url; 212 init_params.active_url = active_url;
115 int32 route_id; 213 int32 route_id;
116 if (!RenderThread::current()->Send( 214 if (!RenderThread::current()->Send(
117 new GpuHostMsg_CreateViewCommandBuffer( 215 new GpuHostMsg_CreateViewCommandBuffer(
118 render_view_id, 216 render_view_id,
119 init_params, 217 init_params,
120 &route_id))) { 218 &route_id))) {
121 return NULL; 219 return NULL;
122 } 220 }
123 221
124 if (route_id == MSG_ROUTING_NONE) 222 if (route_id == MSG_ROUTING_NONE)
125 return NULL; 223 return NULL;
126 224
127 CommandBufferProxy* command_buffer = new CommandBufferProxy(this, route_id); 225 scoped_refptr<CommandBufferProxy> command_buffer =
128 router_.AddRoute(route_id, command_buffer); 226 new CommandBufferProxy(this, route_id);
227 AddRoute(route_id, command_buffer);
129 proxies_[route_id] = command_buffer; 228 proxies_[route_id] = command_buffer;
130 return command_buffer; 229 return command_buffer;
131 #else 230 #else
132 return NULL; 231 return NULL;
133 #endif 232 #endif
134 } 233 }
135 234
136 GpuVideoDecodeAcceleratorHost* GpuChannelHost::CreateVideoDecoder( 235 GpuVideoDecodeAcceleratorHost* GpuChannelHost::CreateVideoDecoder(
137 int command_buffer_route_id, 236 int command_buffer_route_id,
138 const std::vector<int32>& configs, 237 const std::vector<int32>& configs,
139 media::VideoDecodeAccelerator::Client* client) { 238 media::VideoDecodeAccelerator::Client* client) {
239 AutoLock lock(context_lock_);
140 ProxyMap::iterator it = proxies_.find(command_buffer_route_id); 240 ProxyMap::iterator it = proxies_.find(command_buffer_route_id);
141 DCHECK(it != proxies_.end()); 241 DCHECK(it != proxies_.end());
142 CommandBufferProxy* proxy = it->second; 242 CommandBufferProxy* proxy = it->second;
143 return proxy->CreateVideoDecoder(configs, client); 243 return proxy->CreateVideoDecoder(configs, client);
144 } 244 }
145 245
146 CommandBufferProxy* GpuChannelHost::CreateOffscreenCommandBuffer( 246 scoped_refptr<CommandBufferProxy> GpuChannelHost::CreateOffscreenCommandBuffer(
147 const gfx::Size& size, 247 const gfx::Size& size,
148 CommandBufferProxy* share_group, 248 CommandBufferProxy* share_group,
149 const std::string& allowed_extensions, 249 const std::string& allowed_extensions,
150 const std::vector<int32>& attribs, 250 const std::vector<int32>& attribs,
151 const GURL& active_url) { 251 const GURL& active_url) {
152 #if defined(ENABLE_GPU) 252 #if defined(ENABLE_GPU)
253 AutoLock lock(context_lock_);
153 // An error occurred. Need to get the host again to reinitialize it. 254 // An error occurred. Need to get the host again to reinitialize it.
154 if (!channel_.get()) 255 if (!channel_.get())
155 return NULL; 256 return NULL;
156 257
157 GPUCreateCommandBufferConfig init_params; 258 GPUCreateCommandBufferConfig init_params;
158 init_params.share_group_id = 259 init_params.share_group_id =
159 share_group ? share_group->route_id() : MSG_ROUTING_NONE; 260 share_group ? share_group->route_id() : MSG_ROUTING_NONE;
160 init_params.allowed_extensions = allowed_extensions; 261 init_params.allowed_extensions = allowed_extensions;
161 init_params.attribs = attribs; 262 init_params.attribs = attribs;
162 init_params.active_url = active_url; 263 init_params.active_url = active_url;
163 int32 route_id; 264 int32 route_id;
164 if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(size, 265 if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(size,
165 init_params, 266 init_params,
166 &route_id))) { 267 &route_id))) {
167 return NULL; 268 return NULL;
168 } 269 }
169 270
170 if (route_id == MSG_ROUTING_NONE) 271 if (route_id == MSG_ROUTING_NONE)
171 return NULL; 272 return NULL;
172 273
173 CommandBufferProxy* command_buffer = new CommandBufferProxy(this, route_id); 274 scoped_refptr<CommandBufferProxy> command_buffer =
174 router_.AddRoute(route_id, command_buffer); 275 new CommandBufferProxy(this, route_id);
276 AddRoute(route_id, command_buffer);
175 proxies_[route_id] = command_buffer; 277 proxies_[route_id] = command_buffer;
176 return command_buffer; 278 return command_buffer;
177 #else 279 #else
178 return NULL; 280 return NULL;
179 #endif 281 #endif
180 } 282 }
181 283
182 void GpuChannelHost::DestroyCommandBuffer(CommandBufferProxy* command_buffer) { 284 void GpuChannelHost::DestroyCommandBuffer(CommandBufferProxy* command_buffer) {
183 #if defined(ENABLE_GPU) 285 #if defined(ENABLE_GPU)
286 AutoLock lock(context_lock_);
184 Send(new GpuChannelMsg_DestroyCommandBuffer(command_buffer->route_id())); 287 Send(new GpuChannelMsg_DestroyCommandBuffer(command_buffer->route_id()));
185 288
186 // Check the proxy has not already been removed after a channel error. 289 // Check the proxy has not already been removed after a channel error.
187 int route_id = command_buffer->route_id(); 290 int route_id = command_buffer->route_id();
188 if (proxies_.find(command_buffer->route_id()) != proxies_.end()) { 291 if (proxies_.find(command_buffer->route_id()) != proxies_.end())
189 proxies_.erase(route_id); 292 proxies_.erase(route_id);
190 router_.RemoveRoute(route_id); 293 RemoveRoute(route_id);
191 } 294 command_buffer->Orphan();
192
193 delete command_buffer;
194 #endif 295 #endif
195 } 296 }
196 297
197 GpuSurfaceProxy* GpuChannelHost::CreateOffscreenSurface(const gfx::Size& size) { 298 scoped_refptr<GpuSurfaceProxy> GpuChannelHost::CreateOffscreenSurface(
299 const gfx::Size& size) {
198 #if defined(ENABLE_GPU) 300 #if defined(ENABLE_GPU)
301 AutoLock lock(context_lock_);
199 int route_id; 302 int route_id;
200 if (!Send(new GpuChannelMsg_CreateOffscreenSurface(size, &route_id))) 303 if (!Send(new GpuChannelMsg_CreateOffscreenSurface(size, &route_id)))
201 return NULL; 304 return NULL;
202 305
203 scoped_ptr<GpuSurfaceProxy> surface(new GpuSurfaceProxy(this, route_id)); 306 scoped_refptr<GpuSurfaceProxy> surface(new GpuSurfaceProxy(this, route_id));
204 router_.AddRoute(route_id, surface.get()); 307 AddRoute(route_id, surface.get());
205 308
206 return surface.release(); 309 return surface;
207 #endif 310 #endif
208 } 311 }
209 312
210 void GpuChannelHost::DestroySurface(GpuSurfaceProxy* surface) { 313 void GpuChannelHost::DestroySurface(GpuSurfaceProxy* surface) {
211 #if defined(ENABLE_GPU) 314 #if defined(ENABLE_GPU)
315 AutoLock lock(context_lock_);
212 Send(new GpuChannelMsg_DestroySurface(surface->route_id())); 316 Send(new GpuChannelMsg_DestroySurface(surface->route_id()));
213 if (router_.ResolveRoute(surface->route_id()))
214 router_.RemoveRoute(surface->route_id());
215 317
216 delete surface; 318 RemoveRoute(surface->route_id());
319 surface->Orphan();
217 #endif 320 #endif
218 } 321 }
322
323 void GpuChannelHost::AddRoute(
324 int route_id, scoped_refptr<MessageFilter::Listener> listener) {
325 DCHECK(MessageLoopProxy::current());
326
327 MessageLoopProxy* io_loop = RenderProcess::current()->io_message_loop_proxy();
328 io_loop->PostTask(FROM_HERE,
329 NewRunnableMethod(
330 channel_filter_.get(),
331 &GpuChannelHost::MessageFilter::AddRoute,
332 route_id, listener, MessageLoopProxy::current()));
333 }
334
335 void GpuChannelHost::RemoveRoute(int route_id) {
336 MessageLoopProxy* io_loop = RenderProcess::current()->io_message_loop_proxy();
337 io_loop->PostTask(FROM_HERE,
338 NewRunnableMethod(
339 channel_filter_.get(),
340 &GpuChannelHost::MessageFilter::RemoveRoute,
341 route_id));
342 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698