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

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

Powered by Google App Engine
This is Rietveld 408576698