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 #if defined(OS_WIN) | 5 #if defined(OS_WIN) |
6 #include <windows.h> | 6 #include <windows.h> |
7 #endif | 7 #endif |
8 | 8 |
9 #include "content/common/gpu/gpu_channel.h" | 9 #include "content/common/gpu/gpu_channel.h" |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
14 #include "base/message_loop_proxy.h" | 14 #include "base/message_loop_proxy.h" |
15 #include "base/process_util.h" | 15 #include "base/process_util.h" |
16 #include "base/rand_util.h" | 16 #include "base/rand_util.h" |
17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
| 18 #include "base/timer.h" |
18 #include "content/common/child_process.h" | 19 #include "content/common/child_process.h" |
19 #include "content/common/gpu/gpu_channel_manager.h" | 20 #include "content/common/gpu/gpu_channel_manager.h" |
20 #include "content/common/gpu/gpu_messages.h" | 21 #include "content/common/gpu/gpu_messages.h" |
21 #include "content/common/gpu/sync_point_manager.h" | 22 #include "content/common/gpu/sync_point_manager.h" |
22 #include "content/public/common/content_switches.h" | 23 #include "content/public/common/content_switches.h" |
23 #include "crypto/hmac.h" | 24 #include "crypto/hmac.h" |
24 #include "gpu/command_buffer/service/image_manager.h" | 25 #include "gpu/command_buffer/service/image_manager.h" |
25 #include "gpu/command_buffer/service/mailbox_manager.h" | 26 #include "gpu/command_buffer/service/mailbox_manager.h" |
26 #include "gpu/command_buffer/service/gpu_scheduler.h" | 27 #include "gpu/command_buffer/service/gpu_scheduler.h" |
27 #include "ipc/ipc_channel.h" | 28 #include "ipc/ipc_channel.h" |
28 #include "ipc/ipc_channel_proxy.h" | 29 #include "ipc/ipc_channel_proxy.h" |
29 #include "ui/gl/gl_context.h" | 30 #include "ui/gl/gl_context.h" |
30 #include "ui/gl/gl_image.h" | 31 #include "ui/gl/gl_image.h" |
31 #include "ui/gl/gl_surface.h" | 32 #include "ui/gl/gl_surface.h" |
32 | 33 |
33 #if defined(OS_POSIX) | 34 #if defined(OS_POSIX) |
34 #include "ipc/ipc_channel_posix.h" | 35 #include "ipc/ipc_channel_posix.h" |
35 #endif | 36 #endif |
36 | 37 |
37 #if defined(OS_ANDROID) | 38 #if defined(OS_ANDROID) |
38 #include "content/common/gpu/stream_texture_manager_android.h" | 39 #include "content/common/gpu/stream_texture_manager_android.h" |
39 #endif | 40 #endif |
40 | 41 |
41 namespace content { | 42 namespace content { |
42 namespace { | 43 namespace { |
| 44 |
| 45 // How long to wait for an IPC on this channel to be processed before |
| 46 // signaling the need for a preemption. |
| 47 // TODO(backer): This should really be the time between vblank on |
| 48 // platforms that provide this information. |
| 49 const int64 kPreemptPeriodMs = 16; |
| 50 |
| 51 // Generates mailbox names for clients of the GPU process on the IO thread. |
| 52 class MailboxMessageFilter : public IPC::ChannelProxy::MessageFilter { |
| 53 public: |
| 54 explicit MailboxMessageFilter(const std::string& private_key) |
| 55 : channel_(NULL), |
| 56 hmac_(crypto::HMAC::SHA256) { |
| 57 bool success = hmac_.Init(base::StringPiece(private_key)); |
| 58 DCHECK(success); |
| 59 } |
| 60 |
| 61 virtual void OnFilterAdded(IPC::Channel* channel) { |
| 62 DCHECK(!channel_); |
| 63 channel_ = channel; |
| 64 } |
| 65 |
| 66 virtual void OnFilterRemoved() { |
| 67 DCHECK(channel_); |
| 68 channel_ = NULL; |
| 69 } |
| 70 |
| 71 virtual bool OnMessageReceived(const IPC::Message& message) { |
| 72 DCHECK(channel_); |
| 73 |
| 74 bool handled = true; |
| 75 IPC_BEGIN_MESSAGE_MAP(MailboxMessageFilter, message) |
| 76 IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNames, |
| 77 OnGenerateMailboxNames) |
| 78 IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNamesAsync, |
| 79 OnGenerateMailboxNamesAsync) |
| 80 IPC_MESSAGE_UNHANDLED(handled = false) |
| 81 IPC_END_MESSAGE_MAP() |
| 82 |
| 83 return handled; |
| 84 } |
| 85 |
| 86 bool Send(IPC::Message* message) { |
| 87 return channel_->Send(message); |
| 88 } |
| 89 |
| 90 private: |
| 91 ~MailboxMessageFilter() { |
| 92 } |
| 93 |
| 94 // Message handlers. |
| 95 void OnGenerateMailboxNames(unsigned num, std::vector<std::string>* result) { |
| 96 TRACE_EVENT1("gpu", "OnGenerateMailboxNames", "num", num); |
| 97 |
| 98 result->resize(num); |
| 99 |
| 100 for (unsigned i = 0; i < num; ++i) { |
| 101 char name[GL_MAILBOX_SIZE_CHROMIUM]; |
| 102 base::RandBytes(name, sizeof(name) / 2); |
| 103 |
| 104 bool success = hmac_.Sign( |
| 105 base::StringPiece(name, sizeof(name) / 2), |
| 106 reinterpret_cast<unsigned char*>(name) + sizeof(name) / 2, |
| 107 sizeof(name) / 2); |
| 108 DCHECK(success); |
| 109 |
| 110 (*result)[i].assign(name, sizeof(name)); |
| 111 } |
| 112 } |
| 113 |
| 114 void OnGenerateMailboxNamesAsync(unsigned num) { |
| 115 std::vector<std::string> names; |
| 116 OnGenerateMailboxNames(num, &names); |
| 117 Send(new GpuChannelMsg_GenerateMailboxNamesReply(names)); |
| 118 } |
| 119 |
| 120 IPC::Channel* channel_; |
| 121 crypto::HMAC hmac_; |
| 122 }; |
| 123 } // anonymous namespace |
| 124 |
43 // This filter does two things: | 125 // This filter does two things: |
44 // - it counts the number of messages coming in on the channel | 126 // - it counts the number of messages coming in on the channel |
45 // - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO | 127 // - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO |
46 // thread, generating the sync point ID and responding immediately, and then | 128 // thread, generating the sync point ID and responding immediately, and then |
47 // posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message | 129 // posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message |
48 // into the channel's queue. | 130 // into the channel's queue. |
49 class SyncPointMessageFilter : public IPC::ChannelProxy::MessageFilter { | 131 class SyncPointMessageFilter : public IPC::ChannelProxy::MessageFilter { |
50 public: | 132 public: |
51 // Takes ownership of gpu_channel (see below). | 133 // Takes ownership of gpu_channel (see below). |
52 SyncPointMessageFilter(base::WeakPtr<GpuChannel>* gpu_channel, | 134 SyncPointMessageFilter(base::WeakPtr<GpuChannel>* gpu_channel, |
53 scoped_refptr<SyncPointManager> sync_point_manager, | 135 scoped_refptr<SyncPointManager> sync_point_manager, |
54 scoped_refptr<base::MessageLoopProxy> message_loop, | 136 scoped_refptr<base::MessageLoopProxy> message_loop, |
55 scoped_refptr<gpu::RefCountedCounter> | 137 scoped_refptr<gpu::PreemptionFlag> processing_stalled, |
56 unprocessed_messages) | 138 base::AtomicRefCount* unprocessed_messages) |
57 : gpu_channel_(gpu_channel), | 139 : gpu_channel_(gpu_channel), |
58 channel_(NULL), | 140 channel_(NULL), |
59 sync_point_manager_(sync_point_manager), | 141 sync_point_manager_(sync_point_manager), |
60 message_loop_(message_loop), | 142 message_loop_(message_loop), |
| 143 processing_stalled_(processing_stalled), |
61 unprocessed_messages_(unprocessed_messages) { | 144 unprocessed_messages_(unprocessed_messages) { |
62 } | 145 } |
63 | 146 |
64 virtual void OnFilterAdded(IPC::Channel* channel) { | 147 virtual void OnFilterAdded(IPC::Channel* channel) { |
65 DCHECK(!channel_); | 148 DCHECK(!channel_); |
66 channel_ = channel; | 149 channel_ = channel; |
67 } | 150 } |
68 | 151 |
69 virtual void OnFilterRemoved() { | 152 virtual void OnFilterRemoved() { |
70 DCHECK(channel_); | 153 DCHECK(channel_); |
71 channel_ = NULL; | 154 channel_ = NULL; |
72 } | 155 } |
73 | 156 |
74 virtual bool OnMessageReceived(const IPC::Message& message) { | 157 virtual bool OnMessageReceived(const IPC::Message& message) { |
75 DCHECK(channel_); | 158 DCHECK(channel_); |
76 unprocessed_messages_->IncCount(); | 159 base::AtomicRefCountInc(unprocessed_messages_.get()); |
| 160 if (!timer_.IsRunning()) |
| 161 timer_.Start(FROM_HERE, |
| 162 base::TimeDelta::FromMilliseconds(kPreemptPeriodMs), |
| 163 this, &SyncPointMessageFilter::TriggerPreemption); |
77 if (message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) { | 164 if (message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) { |
78 uint32 sync_point = sync_point_manager_->GenerateSyncPoint(); | 165 uint32 sync_point = sync_point_manager_->GenerateSyncPoint(); |
79 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); | 166 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); |
80 GpuCommandBufferMsg_InsertSyncPoint::WriteReplyParams(reply, sync_point); | 167 GpuCommandBufferMsg_InsertSyncPoint::WriteReplyParams(reply, sync_point); |
81 channel_->Send(reply); | 168 channel_->Send(reply); |
82 message_loop_->PostTask(FROM_HERE, base::Bind( | 169 message_loop_->PostTask(FROM_HERE, base::Bind( |
83 &SyncPointMessageFilter::InsertSyncPointOnMainThread, | 170 &SyncPointMessageFilter::InsertSyncPointOnMainThread, |
84 gpu_channel_, | 171 gpu_channel_, |
85 sync_point_manager_, | 172 sync_point_manager_, |
86 message.routing_id(), | 173 message.routing_id(), |
87 sync_point, | 174 sync_point, |
88 unprocessed_messages_)); | 175 unprocessed_messages_.get())); |
89 return true; | 176 return true; |
90 } else if (message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) { | 177 } else if (message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) { |
91 // This message should not be sent explicitly by the renderer. | 178 // This message should not be sent explicitly by the renderer. |
92 NOTREACHED(); | 179 NOTREACHED(); |
93 unprocessed_messages_->DecCount(); | 180 base::AtomicRefCountDec(unprocessed_messages_.get()); |
94 return true; | 181 return true; |
95 } else { | 182 } else { |
96 return false; | 183 return false; |
97 } | 184 } |
98 } | 185 } |
99 | 186 |
| 187 void TriggerPreemption() { |
| 188 if (!base::AtomicRefCountIsZero(unprocessed_messages_.get())) |
| 189 processing_stalled_->Set(); |
| 190 } |
| 191 |
| 192 void ReschedulePreemption() { |
| 193 processing_stalled_->Reset(); |
| 194 if (timer_.IsRunning()) |
| 195 timer_.Reset(); |
| 196 } |
| 197 |
100 protected: | 198 protected: |
101 virtual ~SyncPointMessageFilter() { | 199 virtual ~SyncPointMessageFilter() { |
102 message_loop_->PostTask(FROM_HERE, base::Bind( | 200 message_loop_->PostTask(FROM_HERE, base::Bind( |
103 &SyncPointMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_)); | 201 &SyncPointMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_)); |
104 } | 202 } |
105 | 203 |
106 private: | 204 private: |
107 static void InsertSyncPointOnMainThread( | 205 static void InsertSyncPointOnMainThread( |
108 base::WeakPtr<GpuChannel>* gpu_channel, | 206 base::WeakPtr<GpuChannel>* gpu_channel, |
109 scoped_refptr<SyncPointManager> manager, | 207 scoped_refptr<SyncPointManager> manager, |
110 int32 routing_id, | 208 int32 routing_id, |
111 uint32 sync_point, | 209 uint32 sync_point, |
112 scoped_refptr<gpu::RefCountedCounter> unprocessed_messages_) { | 210 base::AtomicRefCount* unprocessed_messages) { |
113 // This function must ensure that the sync point will be retired. Normally | 211 // This function must ensure that the sync point will be retired. Normally |
114 // we'll find the stub based on the routing ID, and associate the sync point | 212 // we'll find the stub based on the routing ID, and associate the sync point |
115 // with it, but if that fails for any reason (channel or stub already | 213 // with it, but if that fails for any reason (channel or stub already |
116 // deleted, invalid routing id), we need to retire the sync point | 214 // deleted, invalid routing id), we need to retire the sync point |
117 // immediately. | 215 // immediately. |
118 if (gpu_channel->get()) { | 216 if (gpu_channel->get()) { |
119 GpuCommandBufferStub* stub = gpu_channel->get()->LookupCommandBuffer( | 217 GpuCommandBufferStub* stub = gpu_channel->get()->LookupCommandBuffer( |
120 routing_id); | 218 routing_id); |
121 if (stub) { | 219 if (stub) { |
122 stub->AddSyncPoint(sync_point); | 220 stub->AddSyncPoint(sync_point); |
123 GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point); | 221 GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point); |
124 gpu_channel->get()->OnMessageReceived(message); | 222 gpu_channel->get()->OnMessageReceived(message); |
125 return; | 223 return; |
126 } else { | 224 } else { |
127 unprocessed_messages_->DecCount(); | 225 base::AtomicRefCountDec(unprocessed_messages); |
128 } | 226 } |
129 } | 227 } |
130 manager->RetireSyncPoint(sync_point); | 228 manager->RetireSyncPoint(sync_point); |
131 } | 229 } |
132 | 230 |
133 static void DeleteWeakPtrOnMainThread( | 231 static void DeleteWeakPtrOnMainThread( |
134 base::WeakPtr<GpuChannel>* gpu_channel) { | 232 base::WeakPtr<GpuChannel>* gpu_channel) { |
135 delete gpu_channel; | 233 delete gpu_channel; |
136 } | 234 } |
137 | 235 |
138 // NOTE: this is a pointer to a weak pointer. It is never dereferenced on the | 236 // NOTE: this is a pointer to a weak pointer. It is never dereferenced on the |
139 // IO thread, it's only passed through - therefore the WeakPtr assumptions are | 237 // IO thread, it's only passed through - therefore the WeakPtr assumptions are |
140 // respected. | 238 // respected. |
141 base::WeakPtr<GpuChannel>* gpu_channel_; | 239 base::WeakPtr<GpuChannel>* gpu_channel_; |
142 IPC::Channel* channel_; | 240 IPC::Channel* channel_; |
143 scoped_refptr<SyncPointManager> sync_point_manager_; | 241 scoped_refptr<SyncPointManager> sync_point_manager_; |
144 scoped_refptr<base::MessageLoopProxy> message_loop_; | 242 scoped_refptr<base::MessageLoopProxy> message_loop_; |
145 scoped_refptr<gpu::RefCountedCounter> unprocessed_messages_; | 243 scoped_refptr<gpu::PreemptionFlag> processing_stalled_; |
| 244 scoped_ptr<base::AtomicRefCount> unprocessed_messages_; |
| 245 base::OneShotTimer<SyncPointMessageFilter> timer_; |
146 }; | 246 }; |
147 | 247 |
148 // Generates mailbox names for clients of the GPU process on the IO thread. | |
149 class MailboxMessageFilter : public IPC::ChannelProxy::MessageFilter { | |
150 public: | |
151 explicit MailboxMessageFilter(const std::string& private_key) | |
152 : channel_(NULL), | |
153 hmac_(crypto::HMAC::SHA256) { | |
154 bool success = hmac_.Init(base::StringPiece(private_key)); | |
155 DCHECK(success); | |
156 } | |
157 | |
158 virtual void OnFilterAdded(IPC::Channel* channel) { | |
159 DCHECK(!channel_); | |
160 channel_ = channel; | |
161 } | |
162 | |
163 virtual void OnFilterRemoved() { | |
164 DCHECK(channel_); | |
165 channel_ = NULL; | |
166 } | |
167 | |
168 virtual bool OnMessageReceived(const IPC::Message& message) { | |
169 DCHECK(channel_); | |
170 | |
171 bool handled = true; | |
172 IPC_BEGIN_MESSAGE_MAP(MailboxMessageFilter, message) | |
173 IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNames, | |
174 OnGenerateMailboxNames) | |
175 IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNamesAsync, | |
176 OnGenerateMailboxNamesAsync) | |
177 IPC_MESSAGE_UNHANDLED(handled = false) | |
178 IPC_END_MESSAGE_MAP() | |
179 | |
180 return handled; | |
181 } | |
182 | |
183 bool Send(IPC::Message* message) { | |
184 return channel_->Send(message); | |
185 } | |
186 | |
187 private: | |
188 ~MailboxMessageFilter() { | |
189 } | |
190 | |
191 // Message handlers. | |
192 void OnGenerateMailboxNames(unsigned num, std::vector<std::string>* result) { | |
193 TRACE_EVENT1("gpu", "OnGenerateMailboxNames", "num", num); | |
194 | |
195 result->resize(num); | |
196 | |
197 for (unsigned i = 0; i < num; ++i) { | |
198 char name[GL_MAILBOX_SIZE_CHROMIUM]; | |
199 base::RandBytes(name, sizeof(name) / 2); | |
200 | |
201 bool success = hmac_.Sign( | |
202 base::StringPiece(name, sizeof(name) / 2), | |
203 reinterpret_cast<unsigned char*>(name) + sizeof(name) / 2, | |
204 sizeof(name) / 2); | |
205 DCHECK(success); | |
206 | |
207 (*result)[i].assign(name, sizeof(name)); | |
208 } | |
209 } | |
210 | |
211 void OnGenerateMailboxNamesAsync(unsigned num) { | |
212 std::vector<std::string> names; | |
213 OnGenerateMailboxNames(num, &names); | |
214 Send(new GpuChannelMsg_GenerateMailboxNamesReply(names)); | |
215 } | |
216 | |
217 IPC::Channel* channel_; | |
218 crypto::HMAC hmac_; | |
219 }; | |
220 } // anonymous namespace | |
221 | |
222 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, | 248 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, |
223 GpuWatchdog* watchdog, | 249 GpuWatchdog* watchdog, |
224 gfx::GLShareGroup* share_group, | 250 gfx::GLShareGroup* share_group, |
225 gpu::gles2::MailboxManager* mailbox, | 251 gpu::gles2::MailboxManager* mailbox, |
226 int client_id, | 252 int client_id, |
227 bool software) | 253 bool software) |
228 : gpu_channel_manager_(gpu_channel_manager), | 254 : gpu_channel_manager_(gpu_channel_manager), |
229 unprocessed_messages_(new gpu::RefCountedCounter), | 255 unprocessed_messages_(NULL), |
| 256 processing_stalled_(new gpu::PreemptionFlag), |
230 client_id_(client_id), | 257 client_id_(client_id), |
231 share_group_(share_group ? share_group : new gfx::GLShareGroup), | 258 share_group_(share_group ? share_group : new gfx::GLShareGroup), |
232 mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager), | 259 mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager), |
233 image_manager_(new gpu::gles2::ImageManager), | 260 image_manager_(new gpu::gles2::ImageManager), |
234 watchdog_(watchdog), | 261 watchdog_(watchdog), |
235 software_(software), | 262 software_(software), |
236 handle_messages_scheduled_(false), | 263 handle_messages_scheduled_(false), |
237 processed_get_state_fast_(false), | 264 processed_get_state_fast_(false), |
238 currently_processing_message_(NULL), | 265 currently_processing_message_(NULL), |
239 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 266 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
(...skipping 19 matching lines...) Expand all Loading... |
259 channel_.reset(new IPC::SyncChannel( | 286 channel_.reset(new IPC::SyncChannel( |
260 channel_id_, | 287 channel_id_, |
261 IPC::Channel::MODE_SERVER, | 288 IPC::Channel::MODE_SERVER, |
262 this, | 289 this, |
263 io_message_loop, | 290 io_message_loop, |
264 false, | 291 false, |
265 shutdown_event)); | 292 shutdown_event)); |
266 | 293 |
267 base::WeakPtr<GpuChannel>* weak_ptr(new base::WeakPtr<GpuChannel>( | 294 base::WeakPtr<GpuChannel>* weak_ptr(new base::WeakPtr<GpuChannel>( |
268 weak_factory_.GetWeakPtr())); | 295 weak_factory_.GetWeakPtr())); |
269 scoped_refptr<SyncPointMessageFilter> filter(new SyncPointMessageFilter( | 296 unprocessed_messages_ = new base::AtomicRefCount(0); |
| 297 filter_ = new SyncPointMessageFilter( |
270 weak_ptr, | 298 weak_ptr, |
271 gpu_channel_manager_->sync_point_manager(), | 299 gpu_channel_manager_->sync_point_manager(), |
272 base::MessageLoopProxy::current(), | 300 base::MessageLoopProxy::current(), |
273 unprocessed_messages_)); | 301 processing_stalled_, |
274 channel_->AddFilter(filter); | 302 unprocessed_messages_); |
| 303 io_message_loop_ = io_message_loop; |
| 304 channel_->AddFilter(filter_); |
275 | 305 |
276 channel_->AddFilter( | 306 channel_->AddFilter( |
277 new MailboxMessageFilter(mailbox_manager_->private_key())); | 307 new MailboxMessageFilter(mailbox_manager_->private_key())); |
278 | 308 |
279 return true; | 309 return true; |
280 } | 310 } |
281 | 311 |
282 std::string GpuChannel::GetChannelName() { | 312 std::string GpuChannel::GetChannelName() { |
283 return channel_id_; | 313 return channel_id_; |
284 } | 314 } |
285 | 315 |
286 #if defined(OS_POSIX) | 316 #if defined(OS_POSIX) |
287 int GpuChannel::TakeRendererFileDescriptor() { | 317 int GpuChannel::TakeRendererFileDescriptor() { |
288 if (!channel_.get()) { | 318 if (!channel_.get()) { |
289 NOTREACHED(); | 319 NOTREACHED(); |
290 return -1; | 320 return -1; |
291 } | 321 } |
292 return channel_->TakeClientFileDescriptor(); | 322 return channel_->TakeClientFileDescriptor(); |
293 } | 323 } |
294 #endif // defined(OS_POSIX) | 324 #endif // defined(OS_POSIX) |
295 | 325 |
296 bool GpuChannel::OnMessageReceived(const IPC::Message& message) { | 326 bool GpuChannel::OnMessageReceived(const IPC::Message& message) { |
297 // Drop the count that was incremented on the IO thread because we are | |
298 // about to process that message. | |
299 unprocessed_messages_->DecCount(); | |
300 if (log_messages_) { | 327 if (log_messages_) { |
301 DVLOG(1) << "received message @" << &message << " on channel @" << this | 328 DVLOG(1) << "received message @" << &message << " on channel @" << this |
302 << " with type " << message.type(); | 329 << " with type " << message.type(); |
303 } | 330 } |
304 | 331 |
305 // Control messages are not deferred and can be handled out of order with | 332 // Control messages are not deferred and can be handled out of order with |
306 // respect to routed ones. | 333 // respect to routed ones. |
307 if (message.routing_id() == MSG_ROUTING_CONTROL) | 334 if (message.routing_id() == MSG_ROUTING_CONTROL) { |
| 335 MessageProcessed(); |
308 return OnControlMessageReceived(message); | 336 return OnControlMessageReceived(message); |
| 337 } |
309 | 338 |
| 339 bool message_processed = true; |
310 if (message.type() == GpuCommandBufferMsg_GetStateFast::ID) { | 340 if (message.type() == GpuCommandBufferMsg_GetStateFast::ID) { |
311 if (processed_get_state_fast_) { | 341 if (processed_get_state_fast_) { |
312 // Require a non-GetStateFast message in between two GetStateFast | 342 // Require a non-GetStateFast message in between two GetStateFast |
313 // messages, to ensure progress is made. | 343 // messages, to ensure progress is made. |
314 std::deque<IPC::Message*>::iterator point = deferred_messages_.begin(); | 344 std::deque<IPC::Message*>::iterator point = deferred_messages_.begin(); |
315 | 345 |
316 while (point != deferred_messages_.end() && | 346 while (point != deferred_messages_.end() && |
317 (*point)->type() == GpuCommandBufferMsg_GetStateFast::ID) { | 347 (*point)->type() == GpuCommandBufferMsg_GetStateFast::ID) { |
318 ++point; | 348 ++point; |
319 } | 349 } |
320 | 350 |
321 if (point != deferred_messages_.end()) { | 351 if (point != deferred_messages_.end()) { |
322 ++point; | 352 ++point; |
323 } | 353 } |
324 | 354 |
325 deferred_messages_.insert(point, new IPC::Message(message)); | 355 deferred_messages_.insert(point, new IPC::Message(message)); |
326 unprocessed_messages_->IncCount(); | 356 message_processed = false; |
327 } else { | 357 } else { |
328 // Move GetStateFast commands to the head of the queue, so the renderer | 358 // Move GetStateFast commands to the head of the queue, so the renderer |
329 // doesn't have to wait any longer than necessary. | 359 // doesn't have to wait any longer than necessary. |
330 deferred_messages_.push_front(new IPC::Message(message)); | 360 deferred_messages_.push_front(new IPC::Message(message)); |
331 unprocessed_messages_->IncCount(); | 361 message_processed = false; |
332 } | 362 } |
333 } else { | 363 } else { |
334 deferred_messages_.push_back(new IPC::Message(message)); | 364 deferred_messages_.push_back(new IPC::Message(message)); |
335 unprocessed_messages_->IncCount(); | 365 message_processed = false; |
336 } | 366 } |
337 | 367 |
| 368 if (message_processed) |
| 369 MessageProcessed(); |
| 370 |
338 OnScheduled(); | 371 OnScheduled(); |
339 | 372 |
340 return true; | 373 return true; |
341 } | 374 } |
342 | 375 |
343 void GpuChannel::OnChannelError() { | 376 void GpuChannel::OnChannelError() { |
344 gpu_channel_manager_->RemoveChannel(client_id_); | 377 gpu_channel_manager_->RemoveChannel(client_id_); |
345 } | 378 } |
346 | 379 |
347 bool GpuChannel::Send(IPC::Message* message) { | 380 bool GpuChannel::Send(IPC::Message* message) { |
(...skipping 10 matching lines...) Expand all Loading... |
358 return false; | 391 return false; |
359 } | 392 } |
360 | 393 |
361 return channel_->Send(message); | 394 return channel_->Send(message); |
362 } | 395 } |
363 | 396 |
364 void GpuChannel::RequeueMessage() { | 397 void GpuChannel::RequeueMessage() { |
365 DCHECK(currently_processing_message_); | 398 DCHECK(currently_processing_message_); |
366 deferred_messages_.push_front( | 399 deferred_messages_.push_front( |
367 new IPC::Message(*currently_processing_message_)); | 400 new IPC::Message(*currently_processing_message_)); |
368 unprocessed_messages_->IncCount(); | 401 base::AtomicRefCountInc(unprocessed_messages_); |
369 currently_processing_message_ = NULL; | 402 currently_processing_message_ = NULL; |
370 } | 403 } |
371 | 404 |
372 void GpuChannel::OnScheduled() { | 405 void GpuChannel::OnScheduled() { |
373 if (handle_messages_scheduled_) | 406 if (handle_messages_scheduled_) |
374 return; | 407 return; |
375 // Post a task to handle any deferred messages. The deferred message queue is | 408 // Post a task to handle any deferred messages. The deferred message queue is |
376 // not emptied here, which ensures that OnMessageReceived will continue to | 409 // not emptied here, which ensures that OnMessageReceived will continue to |
377 // defer newly received messages until the ones in the queue have all been | 410 // defer newly received messages until the ones in the queue have all been |
378 // handled by HandleMessage. HandleMessage is invoked as a | 411 // handled by HandleMessage. HandleMessage is invoked as a |
(...skipping 30 matching lines...) Expand all Loading... |
409 gfx::Size(), | 442 gfx::Size(), |
410 disallowed_features_, | 443 disallowed_features_, |
411 init_params.allowed_extensions, | 444 init_params.allowed_extensions, |
412 init_params.attribs, | 445 init_params.attribs, |
413 init_params.gpu_preference, | 446 init_params.gpu_preference, |
414 *route_id, | 447 *route_id, |
415 surface_id, | 448 surface_id, |
416 watchdog_, | 449 watchdog_, |
417 software_, | 450 software_, |
418 init_params.active_url)); | 451 init_params.active_url)); |
419 if (preempt_by_counter_.get()) | 452 if (preemption_flag_.get()) |
420 stub->SetPreemptByCounter(preempt_by_counter_); | 453 stub->SetPreemptByFlag(preemption_flag_); |
421 router_.AddRoute(*route_id, stub.get()); | 454 router_.AddRoute(*route_id, stub.get()); |
422 stubs_.AddWithID(stub.release(), *route_id); | 455 stubs_.AddWithID(stub.release(), *route_id); |
423 #endif // ENABLE_GPU | 456 #endif // ENABLE_GPU |
424 } | 457 } |
425 | 458 |
426 GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) { | 459 GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) { |
427 return stubs_.Lookup(route_id); | 460 return stubs_.Lookup(route_id); |
428 } | 461 } |
429 | 462 |
430 void GpuChannel::CreateImage( | 463 void GpuChannel::CreateImage( |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 } | 508 } |
476 | 509 |
477 void GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) { | 510 void GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) { |
478 router_.AddRoute(route_id, listener); | 511 router_.AddRoute(route_id, listener); |
479 } | 512 } |
480 | 513 |
481 void GpuChannel::RemoveRoute(int32 route_id) { | 514 void GpuChannel::RemoveRoute(int32 route_id) { |
482 router_.RemoveRoute(route_id); | 515 router_.RemoveRoute(route_id); |
483 } | 516 } |
484 | 517 |
485 void GpuChannel::SetPreemptByCounter( | 518 void GpuChannel::SetPreemptByFlag( |
486 scoped_refptr<gpu::RefCountedCounter> preempt_by_counter) { | 519 scoped_refptr<gpu::PreemptionFlag> preemption_flag) { |
487 preempt_by_counter_ = preempt_by_counter; | 520 preemption_flag_ = preemption_flag; |
488 | 521 |
489 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); | 522 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); |
490 !it.IsAtEnd(); it.Advance()) { | 523 !it.IsAtEnd(); it.Advance()) { |
491 it.GetCurrentValue()->SetPreemptByCounter(preempt_by_counter_); | 524 it.GetCurrentValue()->SetPreemptByFlag(preemption_flag_); |
492 } | 525 } |
493 } | 526 } |
494 | 527 |
495 GpuChannel::~GpuChannel() { | 528 GpuChannel::~GpuChannel() { |
496 unprocessed_messages_->Reset(); | 529 processing_stalled_->Reset(); |
497 } | 530 } |
498 | 531 |
499 void GpuChannel::OnDestroy() { | 532 void GpuChannel::OnDestroy() { |
500 TRACE_EVENT0("gpu", "GpuChannel::OnDestroy"); | 533 TRACE_EVENT0("gpu", "GpuChannel::OnDestroy"); |
501 gpu_channel_manager_->RemoveChannel(client_id_); | 534 gpu_channel_manager_->RemoveChannel(client_id_); |
502 } | 535 } |
503 | 536 |
504 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { | 537 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { |
505 // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers | 538 // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers |
506 // here. This is so the reply can be delayed if the scheduler is unscheduled. | 539 // here. This is so the reply can be delayed if the scheduler is unscheduled. |
(...skipping 22 matching lines...) Expand all Loading... |
529 handle_messages_scheduled_ = false; | 562 handle_messages_scheduled_ = false; |
530 | 563 |
531 if (!deferred_messages_.empty()) { | 564 if (!deferred_messages_.empty()) { |
532 IPC::Message* m = deferred_messages_.front(); | 565 IPC::Message* m = deferred_messages_.front(); |
533 GpuCommandBufferStub* stub = stubs_.Lookup(m->routing_id()); | 566 GpuCommandBufferStub* stub = stubs_.Lookup(m->routing_id()); |
534 | 567 |
535 if (stub && !stub->IsScheduled()) { | 568 if (stub && !stub->IsScheduled()) { |
536 if (m->type() == GpuCommandBufferMsg_Echo::ID) { | 569 if (m->type() == GpuCommandBufferMsg_Echo::ID) { |
537 stub->DelayEcho(m); | 570 stub->DelayEcho(m); |
538 deferred_messages_.pop_front(); | 571 deferred_messages_.pop_front(); |
539 unprocessed_messages_->DecCount(); | 572 MessageProcessed(); |
540 if (!deferred_messages_.empty()) | 573 if (!deferred_messages_.empty()) |
541 OnScheduled(); | 574 OnScheduled(); |
542 } | 575 } |
543 return; | 576 return; |
544 } | 577 } |
545 | 578 |
| 579 if (stub && stub->IsPreempted()) { |
| 580 OnScheduled(); |
| 581 return; |
| 582 } |
| 583 |
546 scoped_ptr<IPC::Message> message(m); | 584 scoped_ptr<IPC::Message> message(m); |
547 deferred_messages_.pop_front(); | 585 deferred_messages_.pop_front(); |
548 unprocessed_messages_->DecCount(); | 586 bool message_processed = true; |
549 | 587 |
550 processed_get_state_fast_ = | 588 processed_get_state_fast_ = |
551 (message->type() == GpuCommandBufferMsg_GetStateFast::ID); | 589 (message->type() == GpuCommandBufferMsg_GetStateFast::ID); |
552 | 590 |
553 currently_processing_message_ = message.get(); | 591 currently_processing_message_ = message.get(); |
554 bool result = router_.RouteMessage(*message); | 592 bool result = router_.RouteMessage(*message); |
555 currently_processing_message_ = NULL; | 593 currently_processing_message_ = NULL; |
556 | 594 |
557 // Handle deferred control messages. | 595 // Handle deferred control messages. |
558 if (!result) { | 596 if (!result) { |
559 // Respond to sync messages even if router failed to route. | 597 // Respond to sync messages even if router failed to route. |
560 if (message->is_sync()) { | 598 if (message->is_sync()) { |
561 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&*message); | 599 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&*message); |
562 reply->set_reply_error(); | 600 reply->set_reply_error(); |
563 Send(reply); | 601 Send(reply); |
564 } | 602 } |
565 } else { | 603 } else { |
566 // If the command buffer becomes unscheduled as a result of handling the | 604 // If the command buffer becomes unscheduled as a result of handling the |
567 // message but still has more commands to process, synthesize an IPC | 605 // message but still has more commands to process, synthesize an IPC |
568 // message to flush that command buffer. | 606 // message to flush that command buffer. |
569 if (stub) { | 607 if (stub) { |
570 if (stub->HasUnprocessedCommands()) { | 608 if (stub->HasUnprocessedCommands()) { |
571 deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled( | 609 deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled( |
572 stub->route_id())); | 610 stub->route_id())); |
573 unprocessed_messages_->IncCount(); | 611 message_processed = false; |
574 } | 612 } |
575 } | 613 } |
576 } | 614 } |
| 615 if (message_processed) |
| 616 MessageProcessed(); |
577 } | 617 } |
578 | 618 |
579 if (!deferred_messages_.empty()) { | 619 if (!deferred_messages_.empty()) { |
580 OnScheduled(); | 620 OnScheduled(); |
581 } | 621 } |
582 } | 622 } |
583 | 623 |
584 void GpuChannel::OnCreateOffscreenCommandBuffer( | 624 void GpuChannel::OnCreateOffscreenCommandBuffer( |
585 const gfx::Size& size, | 625 const gfx::Size& size, |
586 const GPUCreateCommandBufferConfig& init_params, | 626 const GPUCreateCommandBufferConfig& init_params, |
(...skipping 15 matching lines...) Expand all Loading... |
602 image_manager_.get(), | 642 image_manager_.get(), |
603 size, | 643 size, |
604 disallowed_features_, | 644 disallowed_features_, |
605 init_params.allowed_extensions, | 645 init_params.allowed_extensions, |
606 init_params.attribs, | 646 init_params.attribs, |
607 init_params.gpu_preference, | 647 init_params.gpu_preference, |
608 route_id, | 648 route_id, |
609 0, watchdog_, | 649 0, watchdog_, |
610 software_, | 650 software_, |
611 init_params.active_url)); | 651 init_params.active_url)); |
612 if (preempt_by_counter_.get()) | 652 if (preemption_flag_.get()) |
613 stub->SetPreemptByCounter(preempt_by_counter_); | 653 stub->SetPreemptByFlag(preemption_flag_); |
614 router_.AddRoute(route_id, stub.get()); | 654 router_.AddRoute(route_id, stub.get()); |
615 stubs_.AddWithID(stub.release(), route_id); | 655 stubs_.AddWithID(stub.release(), route_id); |
616 TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer", | 656 TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer", |
617 "route_id", route_id); | 657 "route_id", route_id); |
618 #endif | 658 #endif |
619 | 659 |
620 GpuChannelMsg_CreateOffscreenCommandBuffer::WriteReplyParams( | 660 GpuChannelMsg_CreateOffscreenCommandBuffer::WriteReplyParams( |
621 reply_message, | 661 reply_message, |
622 route_id); | 662 route_id); |
623 Send(reply_message); | 663 Send(reply_message); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 stats.total_processing_commands_time += total_processing_commands_time; | 725 stats.total_processing_commands_time += total_processing_commands_time; |
686 } | 726 } |
687 } | 727 } |
688 | 728 |
689 GpuChannelMsg_CollectRenderingStatsForSurface::WriteReplyParams( | 729 GpuChannelMsg_CollectRenderingStatsForSurface::WriteReplyParams( |
690 reply_message, | 730 reply_message, |
691 stats); | 731 stats); |
692 Send(reply_message); | 732 Send(reply_message); |
693 } | 733 } |
694 | 734 |
| 735 void GpuChannel::MessageProcessed() { |
| 736 base::AtomicRefCountDec(unprocessed_messages_); |
| 737 io_message_loop_->PostTask( |
| 738 FROM_HERE, |
| 739 base::Bind(&SyncPointMessageFilter::ReschedulePreemption, filter_)); |
| 740 } |
| 741 |
695 } // namespace content | 742 } // namespace content |
OLD | NEW |